C++ 复制构造函数、按值传递和按值返回、链操作、编译器
我在两个不同的编译器中编写了这个程序,得到了两个不同的结果:C++ 复制构造函数、按值传递和按值返回、链操作、编译器,c++,copy-constructor,assignment-operator,pass-by-value,chaining,C++,Copy Constructor,Assignment Operator,Pass By Value,Chaining,我在两个不同的编译器中编写了这个程序,得到了两个不同的结果: #include <iostream> using namespace std; class Point { public: int n; Point() { n = 0; } Point operator= (Point p) { return *this; } Point(const Point& p) { cout<<"copy\n"; } ~Point() { cout&l
#include <iostream>
using namespace std;
class Point {
public:
int n;
Point() { n = 0; }
Point operator= (Point p) { return *this; }
Point(const Point& p) { cout<<"copy\n"; }
~Point() { cout<<"Destruct\n"; }
};
int main() {
Point p1, p2, p3;
p1 = p2 = p3;
return 0;
}
编译器2:
copy
copy
Destruct
copy
Destruct
Destruct
Destruct
Destruct
Destruct
我知道有些编译器通过不调用复制构造函数来优化函数中对象的pass/returnby值。这就是两个结果之间存在差异的原因吗
更重要的是,为什么对代码的p2=p3部分调用复制构造函数两次,而对p1=强>
我不使用C++做很多面向对象编程,这就是为什么我对这个简单问题感到困惑。我非常感谢一些提示您的赋值运算符应该返回
点&
而不是点
,并且它也应该将参数作为参考:
Point &operator = (const Point &p) { return *this; }
否则,可能会发生不必要的复制。最有可能的情况是,在赋值操作符中创建一个副本,然后将返回值复制到
p2
和p1
这点操作符=(点p){return*This;}
不是赋值操作符应该的样子。你还没有安装仪器。谢谢你的回复@Neil。我知道这不是编写赋值运算符的正确方法。我只想知道编译器是如何处理这些代码的,以及为什么编译器可能会遵守不同年份的标准(或者一个编译器在遵守最新标准方面不如另一个编译器完整)。最近的标准要求临时变量通过创建它们的表达式持久化,但较旧的标准对临时变量的生存期没有那么具体,因此编译器可以选择更早地销毁临时变量。复制省略也会使事情复杂化,但这里的情况并非如此(在这两种情况下创建的临时对象数量相同,只是它们的生命周期不同)。感谢您的回复@Sid。我知道编写函数的正确方法(通过引用传递和通过引用返回,以避免不必要的复制和链接)。然而,我只是感到困惑,为什么为p2=p3调用了两次复制构造函数,为p1=返回对象的副本调用了一次?@user,因为Point operator=(Point p){return*this;}
复制了它的参数,又为它的返回值调用了一次。很可能,创建了一个副本,进入赋值操作符,然后将返回的值复制到p2
和p1
。
Point &operator = (const Point &p) { return *this; }