gpt4 book ai didi

当写在一行中时,C++ move 构造函数不使用复合运算符 += 调用

转载 作者:行者123 更新时间:2023-12-05 03:29:08 25 4
gpt4 key购买 nike

我遵循了 stackoverflow 中有关 Move 和 Operator 重载的精彩教程(例如 What are the basic rules and idioms for operator overloading? ),但以下情况让我感到困惑。代码中没有什么特别的,只是在调用特殊成员函数时打印。

主要代码:

    class B {
public:
B() { std::cout << "B::ctor\n"; }

~B() { std::cout << "B::dtor\n"; }

B(B const &b) {
std::cout << "B::copy ctor\n";
}

B &operator=(B const &rhs) {
std::cout << "B::copy assignment\n";
return *this;
}

B(B &&b) {
std::cout << "B::move ctor\n";
}

B &operator=(B &&rhs) {
std::cout << "B::move assignment\n";
return *this;
}

B &operator+=(B const &rhs) {
std::cout << "B::operator+=\n";
return *this;
}
};



int main() {
B b;
std::cout << "=== b = b + b + b ===\n";
b = b + b + b;
}

现在,两个场景,在每个场景中,我对运算符 + 的定义不同:

B operator+(B p1, B const &p2) {
std::cout << "B::operator+\n";
return p1 += p2;
}

整个程序的输出:

B::ctor
=== b = b + b + b ===
B::copy ctor
B::operator+
B::operator+=
B::copy ctor
B::operator+
B::operator+=
B::copy ctor
B::move assignment
B::dtor
B::dtor
B::dtor
B::dtor

第二种情况:

B operator+(B p1, B const &p2) {
std::cout << "B::operator+\n";
p1 += p2;
return p1;
}

输出:

B::ctor
=== b = b + b + b ===
B::copy ctor
B::operator+
B::operator+=
B::move ctor
B::operator+
B::operator+=
B::move ctor
B::move assignment
B::dtor
B::dtor
B::dtor
B::dtor

为什么第二种情况确实给出了预期的结果,正确使用了 move 语义,但第一种情况却到处复制?

我只想补充一点,第二个场景是我阅读的教程中推荐的场景(如上面的链接),但是当我尝试实现它时,我凭直觉写了第一个场景,它给了我错误的行为...

最佳答案

从具有相同1 返回类型T 的函数返回类型T 的局部变量is a special case .

它至少会自动 move 变量,或者,如果编译器足够聪明以执行所谓的 NRVO,则完全消除复制/move 并直接在正确位置构造变量。

函数参数(与常规局部变量不同)不符合 NRVO 的条件,因此您总是会在 (2) 中获得隐式 move 。

这不会发生在 (1) 中。编译器不会分析 += 来理解它返回的内容;此规则仅在 return 的操作数是单个变量时有效。

由于 += 返回左值引用,而您没有std::move 它,因此调用了复制构造函数。


1 或仅在 cv 限定符方面不同的类型。

关于当写在一行中时,C++ move 构造函数不使用复合运算符 += 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71070239/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com