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; }