gpt4 book ai didi

c++ - 使用按值返回在c++中重载赋值运算符

转载 作者:行者123 更新时间:2023-11-30 02:00:33 25 4
gpt4 key购买 nike

考虑:

    class MyObject{
public:
MyObject();
MyObject(int,int);
int x;
int y;
MyObject operator =(MyObject rhs);
};
MyObject::MyObject(int xp, int yp){
x = xp;
y = yp;
}
MyObject MyObject::operator =(MyObject rhs){
MyObject temp;
temp.x = rhs.x;
temp.y = rhs.y;
return temp;
}

int main(){
MyObject one(1,1);
MyObject two(2,2);
MyObject three(3,3);
one = two = three;
cout << one.x << ", " << one.y;
cout << two.x << ", " << two.y;
cout << three.x << ", " << three.y;

}

这样,一,二和三中的变量x和y不变。我知道我应该为MyObject更新成员变量,并通过引用使用return并返回* this以确保正确的行为。但是,返回值一=二=三实际上发生了什么?返回温度实际上在链中最终到达何处,就像一步一步走一样?

最佳答案

在中对赋值运算符的调用

two = three

返回一个临时对象作为右值。这是 MyObject类型,并传递给赋值运算符的下一个调用
one = t

(我使用 t引用临时对象。)

不幸的是,这不会编译,因为赋值运算符期望引用 MyObject&,而不是 MyObject类型的右值。

(您的代码由于各种原因而无法编译,包括大写的 Class和错别字。)

但是,如果您要定义一个带有右值的赋值运算符(即,如果使用C++ 11,则按值,const引用或实际上按右值引用 MyObject&&接受参数),调用将起作用,并且临时对象将复制到函数中。在内部,将进行分配并返回另一个临时对象。

然后,最终的临时对象将超出范围,即不再存在。将无法访问其内容。

感谢乔亚希姆·皮勒博格(Joachim PIleborg)和本杰明·林德利(Benjamin Lindley)的有用评论。

要回答请求以获取更多详细信息,请执行以下操作: MyObject是类类型,并且C++ Standard包含有关类类型的临时对象的生命周期的整个部分(第12.2节)。这里详细介绍了各种复杂的情况,我不会一一解释。但是基本概念如下:
  • C++具有表达式的概念。表达式以及声明和语句是组成程序代码的基本单元。例如,函数调用f(a,b,c)是表达式或类似于a = b的赋值。表达式可以包含其他表达式:a = f(b,c),嵌套在赋值表达式中的函数调用。 C++还引入了全表达式的概念。在前面的示例中,cf(b,c)表达式的一部分,也是a = f(b,c)的一部分,如果未嵌套在另一个表达式中,我们说a = f(b,c)是词法上包含c的完整表达式。
  • 该标准定义了可能创建临时对象的各种情况。一种这样的情况是通过函数调用的值返回对象(也就是返回prvalue,第6.6.3节)。
  • 该标准指出,此类临时对象的生存期在完全评估了包含该临时对象的完整表达式后会终止:

    [...] Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. [...]



    (注意。然后,标准继续定义此规则的几个异常(exception)。但是,赋值运算符的返回值的情况并非此类异常(exception)。)
  • 现在,意味着(类类型的)对象被破坏是什么意思? 首先,它的析构函数被称为(§12.2/ 3)。这也意味着不再可以安全地访问该对象的存储。因此,如果您以某种方式设法在完全表达式的评估结束之前将临时对象的地址存储在指针中,则在评估结束之后取消对该指针的引用通常会导致未定义的行为。
  • 实际上,在许多情况下,这可能意味着:–在一种可能的情况下,我描述了临时对象的整个生命周期:
  • 为了为临时存储提供空间,编译器确保在输入包含full-expression的函数时(在实际评估full-expression之前发生)分配足够的堆栈空间。
  • 在赋值表达式的求值期间,将创建临时项。编译器确保调用其构造函数以初始化为其分配的空间。
  • 然后,可以在评估临时表的一部分的完整表达式的过程中访问或修改该临时表的内容。
  • 当表达式已被完全求值时(在您的情况下,此刻对应于包含赋值表达式的行的末尾),将调用临时函数的析构函数。之后,访问为它分配的内存不再安全,尽管实际上,空间将继续成为当前堆栈帧的一部分,直到对所有发生这种情况的功能进行评估为止。
  • 但是,这仅是可能发生情况的一个示例。在许多情况下,实际上并不需要临时工的创建。编译器可能会执行优化,这意味着从不实际创建临时文件。在这种情况下,编译器仍然必须确保可以创建它,例如它必须确保所需的构造函数和析构函数存在(尽管它们永远不会被调用)。
  • 关于c++ - 使用按值返回在c++中重载赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15015758/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com