编译器忽略显式定义的移动构造函数?
compiler ignores explicitly-defined move constructor?
我想了解为什么以下代码没有调用我的移动构造函数。我使用 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 应该调用移动构造函数,如果我理解正确的话。
这是因为编译器只是通过忽略我的移动构造函数定义来进行优化,还是因为我的假设之一有缺陷?
Foo operator+(const Foo& f, const Foo& g){
Foo h(f.getValue() + g.getValue());
return h;
}
这会调用 NRVO 并绕过使用移动构造函数 return 对象的需要。
在 C++ 中有一个称为省略的概念。
省略允许编译器将各种变量的生命周期合并为一个生命周期——它们的存在被一起省略。
它可以省略用于直接构造相同类型的值的临时变量,或者在简单的 return x;
样式语句中从函数 return 编辑的命名局部变量。
使其合法的构造函数必须存在,但编译器不需要调用它。即使复制或移动 ctor 会产生副作用,也允许省略,因此您的打印语句不会 运行.
所以编译器没有移动——它只是构造了它要直接去的地方的对象!值 h
实际上是 +
.
的实际 return 值
你做完了吗
Foo x = f+f;
编译器可以将 h
、+
和 x
的 return 值省略到一个对象中。
NRVO 和 RVO(名为 return 值优化和 return 值优化)的两个常见案例可以追溯到一段时间以前,但它们只是编译器忽略的特定技术的名称。编译器不会被强制省略,但被允许这样做。在某些情况下,编译器很难进行省略(在一种情况下 IIRC 是不允许的);在每种情况下,都可以调用 move ctor(如果不存在 move,则复制)。一个例子是当你有两个不同的局部变量 return 来自一个函数时;这使得编译器很难合法地用 return 值省略两者。
我想了解为什么以下代码没有调用我的移动构造函数。我使用 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 应该调用移动构造函数,如果我理解正确的话。
这是因为编译器只是通过忽略我的移动构造函数定义来进行优化,还是因为我的假设之一有缺陷?
Foo operator+(const Foo& f, const Foo& g){
Foo h(f.getValue() + g.getValue());
return h;
}
这会调用 NRVO 并绕过使用移动构造函数 return 对象的需要。
在 C++ 中有一个称为省略的概念。
省略允许编译器将各种变量的生命周期合并为一个生命周期——它们的存在被一起省略。
它可以省略用于直接构造相同类型的值的临时变量,或者在简单的 return x;
样式语句中从函数 return 编辑的命名局部变量。
使其合法的构造函数必须存在,但编译器不需要调用它。即使复制或移动 ctor 会产生副作用,也允许省略,因此您的打印语句不会 运行.
所以编译器没有移动——它只是构造了它要直接去的地方的对象!值 h
实际上是 +
.
你做完了吗
Foo x = f+f;
编译器可以将 h
、+
和 x
的 return 值省略到一个对象中。
NRVO 和 RVO(名为 return 值优化和 return 值优化)的两个常见案例可以追溯到一段时间以前,但它们只是编译器忽略的特定技术的名称。编译器不会被强制省略,但被允许这样做。在某些情况下,编译器很难进行省略(在一种情况下 IIRC 是不允许的);在每种情况下,都可以调用 move ctor(如果不存在 move,则复制)。一个例子是当你有两个不同的局部变量 return 来自一个函数时;这使得编译器很难合法地用 return 值省略两者。