gpt4 book ai didi

c++ - 为什么不调用复制构造函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:04:21 29 4
gpt4 key购买 nike

这是一个简单的类头文件和一个主程序。在主程序中,我认为复制构造函数恰好在三种情况下被调用:初始化(显式复制),函数参数按值传递,函数按值返回。然而,似乎其中之一没有被要求,我认为评论中编号的 (3) 或 (4)。对于哪些数字 (1) - (4) 会被调用?谢谢。

X.h:

#include <iostream>

class X
{
public:
X() {std::cout << "default constructor \n";}
X(const X& x) { std::cout << "copy constructor \n";}
};

主要内容:

#include "X.h"

X returnX(X b) // (1) pass by value - call copy constructor?
{
X c = b; // (2) explicit copy - call copy constructor?
return b; // (3) return by value - call copy constructor?
}

int main()
{
X a; // calls default constructor

std::cout << "calling returnX \n\n";
X d = returnX(a); // (4) explicit copy - call copy constructor?
std::cout << "back in main \n";
}

输出:

default constructor
calling returnX

copy constructor
copy constructor
copy constructor
back in main

最佳答案

由于复制在 C++ 中经常发生,而且它可能很昂贵,因此允许编译器省略某些复制(和移动)结构。即使省略的构造函数和/或析构函数具有类似于程序输出的副作用(也就是说,它并不是真正的优化,因为有和没有复制省略的行为是不同的),这种复制省略也是允许的。

根据 12.8 [class.copy] 第 31 段,有四个基本地方可以应用复制省略:

  1. return 语句中直接返回与函数返回类型相同的局部变量。
  2. throw 语句中,最里面的 try block 中的自动变量的拷贝可以在对象被抛出时省略。
  3. 当临时对象未绑定(bind)到引用复制时,它可以被省略。
  4. catch 子句按值捕获对象并且与 throw 语句中的对象类型相同时,可以省略拷贝。

确切的规则稍微复杂一些,但我认为这就是它的要点。考虑到复制省略规则相当严格,很容易抑制复制省略:最简单的方法是使用 identity() 函数:

template <typename T>
T const& identity(T const& object) {
return object;
}
...
X d = identity(returnX(a));

(虽然这个版本也禁止移动构造;使用 T&& 推导类型并适本地返回它应该使移动构造成为可能,但我不太确定返回类型和返回语句是什么应该是)。

关于c++ - 为什么不调用复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20787871/

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