Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;vlaue返回复制构造函数激活_C++_Copy Constructor_Return By Value - Fatal编程技术网

C++ C++;vlaue返回复制构造函数激活

C++ C++;vlaue返回复制构造函数激活,c++,copy-constructor,return-by-value,C++,Copy Constructor,Return By Value,我无法找到以下问题的具体答案: 考虑以下代码: Obj f() { Obj o2; return o2; } int main() { Obj o1 = f(); return 0; } 在没有编译器优化的情况下,复制构造函数被激活了多少次 如果没有移动构造函数,不是一次用于将o2复制到调用函数,另一次用于构造o1吗 如果存在移动构造函数,是不是一次用于将o2复制到调用方函数,另一次用于构造o1(第二次是移动常量)?在C++17之前,有两个复制构造函数调用(即

我无法找到以下问题的具体答案:

考虑以下代码:

Obj f() {
    Obj o2;
    return o2;
}

int main() {
    Obj o1 = f();
    return 0;
}
在没有编译器优化的情况下,复制构造函数被激活了多少次

如果没有移动构造函数,不是一次用于将o2复制到调用函数,另一次用于构造o1吗


如果存在移动构造函数,是不是一次用于将o2复制到调用方函数,另一次用于构造o1(第二次是移动常量)?

在C++17之前,有两个复制构造函数调用(即使它们有副作用,也可以省略)。您可以通过gcc/clang中的
-fno-elide构造函数看到这一点

由于新的临时物化规则,C++17中只涉及一个副本(同样可以省略)



准确地说,它们都是移动,而不是复制。

在C++17之前,是的,有两个复制构造函数调用(即使它们有副作用,也可以省略这两个调用)。您可以通过gcc/clang中的
-fno-elide构造函数看到这一点

由于新的临时物化规则,C++17中只涉及一个副本(同样可以省略)


准确地说,所有这些都是移动,而不是复制。

C++03及之前的版本
Obj
被复制两次。一次通过
return
语句(构造返回值),一次通过复制返回值初始化
o1

C++11和C++14 如果
Obj
有一个可用的移动构造函数,它将移动两次,复制零次。
return
语句必须使用移动,即使返回的表达式是左值。由于语言中的特殊规则,这种“移动优化”是强制性的<即使禁用优化,也不得复制代码>o2
。当初始化
o1
时,会发生第二个移动

如果
Obj
没有移动构造函数或隐式删除了移动构造函数,则会使用复制构造函数两次

如果
Obj
有一个显式删除的移动构造函数,则由于
o1
的初始化尝试使用删除的移动构造函数,因此程序的格式不正确

C++17及更高版本 如果
Obj
具有可用的move构造函数,则在执行
return
语句时将其移动一次。如上所述,编译器必须使用移动而不是复制。
o1
的构造既不涉及复制也不涉及移动。相反,
f()
中的
return
语句初始化
o1
,而不涉及临时变量。这是因为“保证的副本省略”:该语言要求省略副本,即使禁用了优化。这是因为
f()
是一个prvalue,除非有必要,否则prvalue不会具体化(即,实例化为临时对象)。标准创建的“法律虚构”是
f()
实际上返回了创建
Obj
的“配方”,而不是
Obj
本身。在实践中,这可以以与标准早期版本中实现的(可选)返回值优化相同的方式实现:调用方将指向
o1
的指针直接传递到
f
,而
return
语句将
Obj
构造到该指针中

如果
Obj
的move构造函数被隐式删除或不存在,则
return
语句将使用copy构造函数,因此将有一个copy和零个move

如果显式删除了Obj
的move构造函数,则程序的格式与C++11/C++14的情况相同

无论如何 可以优化上述情况下的复制/移动。在涉及多个复制/移动操作的情况下,编译器可以优化其中任何一个或所有操作。

C++03及之前的版本
Obj
被复制两次。一次通过
return
语句(构造返回值),一次通过复制返回值初始化
o1

C++11和C++14 如果
Obj
有一个可用的移动构造函数,它将移动两次,复制零次。
return
语句必须使用移动,即使返回的表达式是左值。由于语言中的特殊规则,这种“移动优化”是强制性的<即使禁用优化,也不得复制代码>o2。当初始化
o1
时,会发生第二个移动

如果
Obj
没有移动构造函数或隐式删除了移动构造函数,则会使用复制构造函数两次

如果
Obj
有一个显式删除的移动构造函数,则由于
o1
的初始化尝试使用删除的移动构造函数,因此程序的格式不正确

C++17及更高版本 如果
Obj
具有可用的move构造函数,则在执行
return
语句时将其移动一次。如上所述,编译器必须使用移动而不是复制。
o1
的构造既不涉及复制也不涉及移动。相反,
f()
中的
return
语句初始化
o1
,而不涉及临时变量。这是因为“保证的副本省略”:该语言要求省略副本,即使禁用了优化。这是因为
f()
是一个prvalue,除非有必要,否则prvalue不会具体化(即,实例化为临时对象)。标准创建的“法律虚构”是
f()
实际上返回了创建
Obj
的“配方”,而不是
Obj
本身。在实践中,这可以通过与(可选)返回值optimiza相同的方式实现