在这里,按值返回result 是完全有效的。现代编译器将应用 NRVO named return value optimization,这样就不需要复制了。如果一个指针是通过求和操作返回的,那就更混乱了。
关于您的其他问题(如果我理解正确的话),使用= 并不总是涉及复制。例如,还有一个移动赋值运算符,它只是将rvalue 引用移动到对象中而不是复制它。也有应用复制省略的情况(与上面相同的链接)并允许完全避免复制和移动语义。
在以下示例中,您可以看到编译器几乎忽略了复制或移动 (live demo)
#include <string>
#include <iostream>
#include <iomanip>
struct Point{
Point() = default;
Point(double x, double y):x(x),y(y){}
Point(const Point &p):x(p.x),y(p.y){
std::cout << "copy construct" << std::endl;}
Point(Point&& p):x(std::move(p.x)),y(std::move(p.y)){
std::cout << "move construct" << std::endl;}
Point& operator=(const Point& p){
x = p.x;
y = p.y;
std::cout << "copy assign" << std::endl;
return *this;
}
Point& operator=(Point&& p){
x = std::move(p.x);
y = std::move(p.y);
std::cout << "move assign" << std::endl;
return *this;
}
double x,y;
};
std::ostream& operator<<(std::ostream& out, const Point& p)
{
out << std::setw(5) << p.x << std::setw(5) << p.x << std::flush;
return out;
}
Point operator+(const Point& p1, const Point &p2)
{
return Point(p1.x+p2.x,p1.y+p2.y);
}
Point sum1(const Point& p1, const Point &p2)
{
return Point(p1.x+p2.x,p1.y+p2.y);
}
Point sum2(const Point& p1, const Point &p2)
{
Point result;
result.x = p1.x+p2.x;
result.y = p1.y+p2.y;
return result;
}
int main()
{
Point p1(1,0), p2(0,1);
auto r1 = sum2(p1,p2);
auto r2 = sum1(p1,p2);
auto r3 = r1+r2;
auto r4 = r3; // <- only this calls the copy constructor
std::cout << "r3 = ("<< r3 << ")"<< std::endl;
}
打印出来:
copy construct
r3 = ( 2 2)
作为提示,您可以重载+ 运算符,如示例所示,以更易读的方式编写求和。