复制省略和返回值优化
复制省略和返回值优化是编译器可能存在的优化机制。今天在测试右值没有std::move的时候是否会优先匹配调用移动构造和移动赋值函数时发现这个机制。
#include <iostream>
using std::cout;
using std::endl;
class MoveTest {
public:
MoveTest(int i) :
_i(i) {
cout << "Normal Constructor" << endl;
}
MoveTest(const MoveTest& other) :
_i(other._i) {
cout << "Copy Constructor" << endl;
} // = delete;
MoveTest& operator=(const MoveTest& other) {
return *this;
} //= delete;
MoveTest(MoveTest&& o) {
_i = o._i;
cout << "Move Constructor" << endl;
}
MoveTest& operator=(const MoveTest&& o) {
cout << "Move Assign" << endl;
return *this;
}
//private:
int _i;
};
MoveTest get() {
MoveTest t = MoveTest(2);
cout << "get() construct" << endl;
return t; //MoveTest(1);
}
int main(int argc, char **argv) {
MoveTest t(get());
cout << t._i << endl;
t = get();
}
Result:
Normal Constructor
get() construct
2
Normal Constructor
get() construct
Move Assign
由ConsolePrint可以发现
MoveTest t(get());
没有调用移动构造或拷贝构造。
然后去stackflow寻找答案
What are copy elision and return value optimization?
大致介绍了由于编译器可能存在copy elision and returnvalue optimization机制,copy/move constructor可能不被调用,所以不能在这两个函数内写关键逻辑,可能会出错。
注意
然而并不是说存在这个机制就并不需要move/copy constructor,如果delete二者,编译器会出错。
If a call to a copy or move constructor is elided, that constructor must still exist and must be accessible. This ensures that copy elision does not allow copying objects which are not normally copyable, e.g. because they have a private or deleted copy/move constructor.
我也进行了如下测试
#include <iostream>
using std::cout;
using std::endl;
class MoveTest {
public:
MoveTest(int i) :
_i(i) {
cout << "Normal Constructor" << endl;
}
MoveTest(const MoveTest& other)
// :
// _i(other._i) {
// cout << "Copy Constructor" << endl;
// }
= delete;
MoveTest& operator=(const MoveTest& other) {
return *this;
} //= delete;
MoveTest(MoveTest&& o)
// {
// _i = o._i;
// cout << "Move Constructor" << endl;
// }
= delete;
MoveTest& operator=(const MoveTest&& o) {
cout << "Move Assign" << endl;
return *this;
}
//private:
int _i;
};
MoveTest get() {
MoveTest t = MoveTest(2); //use of deleted function ‘MoveTest::MoveTest(MoveTest&&)’
cout << "get() construct" << endl;
return t; //MoveTest(1); //use of deleted function ‘MoveTest::MoveTest(MoveTest&&)’
}
int main(int argc, char **argv) {
MoveTest t(get()); //use of deleted function ‘MoveTest::MoveTest(MoveTest&&)’
cout << t._i << endl;
t = get();
}
出现3处标红报错,可以说明的确如此。
由get()函数return语句的报错,可以想想如果不存在优化机制,此编译器可能使用的移动构造传递返回值。
测试编译器
gcc version 6.5.0 20181026 (Ubuntu 6.5.0-2ubuntu1~16.04)