gpt4 book ai didi

c++ - 编译器忽略显式定义的 move 构造函数?

转载 作者:行者123 更新时间:2023-11-30 02:32:13 25 4
gpt4 key购买 nike

我试图理解为什么下面的代码没有调用我的 move 构造函数。我使用 gnu++11 编译。

#include <iostream>

class Foo{
int value;
public:
Foo(int v){ value = v; }
Foo(const Foo& g){
value = g.value;
std::cout << "copy construct called\n";
}
Foo(Foo&& g){
value = g.value;
std::cout << "move construct called\n";
}
int getValue() const{ return value; }
};

Foo operator+(const Foo& f, const Foo& g){
Foo h(f.getValue() + g.getValue());
return h;
}

void sayValue(const Foo& f){
std::cout << f.getValue() << std::endl;
}

int main(){
Foo f(5);
sayValue(f + f);
return 0;
}

运行以下代码只是打印 10 而不是

move construct called
10

如我所料。我期望这是因为当我为 Foo 定义 + 二元运算符时,返回 Foo g 应该调用 move 构造函数,如果我理解正确的话。

这是因为编译器只是通过忽略我的 move 构造函数定义来进行优化,还是因为我的假设之一有缺陷?

最佳答案

在 C++ 中有一个称为省略的概念。

省略允许编译器将各种变量的生命周期合并为一个生命周期——它们的存在被一起省略。

它可以省略用于直接构造相同类型的值的临时变量,或者在简单的 return x; 样式语句中从函数返回的命名局部变量。

使其合法的构造函数必须存在,但编译器不需要调用它。即使复制或 move ctor 会产生副作用,也允许发生省略,因此您的打印语句不会运行。

所以编译器没有 move ——它只是在它要直接去的地方构造了对象!值 h 实际上是 + 的实际返回值。

你做完了吗

Foo x = f+f;

编译器可以将 h+ 的返回值和 x 省略为一个对象。


NRVO 和 RVO(命名返回值优化和返回值优化)这两个常见案例可以追溯到一段时间以前,但它们只是编译器要省略的特定技术的名称。编译器不会被强制省略,但被允许这样做。在某些情况下,编译器很难进行省略(在一种情况下 IIRC 是不允许的);在每种情况下,都可以调用 move ctor(如果不存在 move,则复制)。一个例子是当你从一个函数返回两个不同的局部变量时;这使得编译器很难合法地用返回值省略两者。

关于c++ - 编译器忽略显式定义的 move 构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36670402/

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