#include<bits/stdc++.h>
using namespace std;
class A{
public:
int data;
A(int s){
data=s;
}
A(A &obj){
data=obj.data;
cout<<"Copy"<<endl;
}
};
A getobject(){
A obj(2);
return obj;
}
int main(){
A newobj = getobject();
return 0;
}
我的理解是,首先创建临时对象来存储 getobject() 函数返回的对象,然后将临时对象复制到 newobj 中,从而调用复制构造函数。如果这是真的,那么是否就像我们将返回的 obj 存储到临时对象中时一样,也使用了复制机制,如果不是,那么会怎样?
注意-请忽略命名空间和库。
我的理解是,首先创建临时对象来存储 getobject() 函数返回的对象,然后将临时对象复制到 newobj 中,从而调用复制构造函数。如果这是真的,那么是否就像我们将返回的 obj 存储到临时对象中时一样,也使用了复制机制,如果不是,那么会怎样?
自 C++17 起,这些都不是真的。从根本上来说,代码中只有两个对象:从变量
obj
实例化的对象和从变量 newobj
实例化的对象。即使原则上也不存在临时对象。
getobject()
是一个纯右值表达式,它立即初始化其结果对象,它与函数返回值中的表达式是newobj
,即newobj
是从表达式obj
复制初始化的,除了有一个特殊的当 return
语句中的表达式仅命名局部变量时,遵循此规则。在这种情况下,obj
被认为是xvalue(即右值)而不是通常的左值,因此将使用移动构造函数而不是复制构造函数。 (从技术上讲,最后一句话仅在 C++23 后才成立,之前它更复杂,但这里的结果相同。)
从函数返回时不再进行返回值优化或复制省略,尽管 C++17 规则被随意称为“强制复制省略”。唯一仍然可能的复制省略是命名的返回值优化,它将
obj
与 newobj
一起识别,以便总共只有一个没有任何副本或移动的对象存在。