这是一个完整的程序:
#include <iostream>
using std::cout;
using std::endl;
using std::move;
int count {0}; // global for monitoring
class Triple {
public:
Triple() = default; // C++11 use default constructor despite other constructors being declared
Triple(Triple&&) = default;
Triple(const Triple& t) : // copy constructor
Triple(t.mX, t.mY, t.mZ) {
count++;
}
Triple(const int x, const int y, const int z) :
mX{ x }, mY{ y }, mZ{ z } {
}
const Triple& operator +=(const Triple& rhs) {
mX += rhs.mX;
mY += rhs.mY;
mZ += rhs.mZ;
return *this;
}
int x() const;
int y() const;
int z() const;
private:
int mX{ 0 }; // c++11 member initialization
int mY{ 0 };
int mZ{ 0 };
};
#if 0
inline Triple operator+(const Triple& lhs, const Triple& rhs) {
Triple left { lhs };
left += rhs;
return left;
}
#else
inline Triple operator+(Triple left, const Triple& rhs) {
left += rhs;
return left;
}
#endif
int main()
{
Triple a,b;
cout << "initial value of count is: " << count << endl;
auto result { a+b };
cout << "final value of count is: " << count << endl;
}
有趣的是复制构造函数有一个副作用,并且有两个版本operator+
需要考虑。
情况1
inline Triple operator+(const Triple& lhs, const Triple& rhs) {
Triple left { lhs };
left += rhs;
return left;
}
案例2
inline Triple operator+(Triple left, const Triple& rhs) {
left += rhs;
return left;
}
Visual Studio 2015 给出了相同的结果,打印结果为1
. 但是 gcc 4.8.4 给出2
了案例 1。
这个复制省略的总结※</sup> 声明“<em>这不是函数参数”,这让我认为 VS 是错误的。那是对的吗?
但是,为什么在这条规则中要特别对待形式参数名称呢?为什么它不完全像任何其他局部变量?
(我并不是说优化器会根据调用约定并根据调用者和被调用者的单独编译来解决问题,而只是说为什么不允许这样做。)
编辑:如果输出1
是正确的,这与省略规则有何关系?
注意※:我发现这段文字是从公开的N3690中的 §12.8 第 31 段复制而来的。