0

cppreference中据说

当操作数是与函数返回类型相同的类类型(忽略 cv 限定)的纯右值时,复制/移动构造函数不需要在 return 语句中出现或可访问:

T f() {
    return T();
}

f(); // only one call to default constructor of T

我是否理解这一点,并且为了使上述示例正常工作,不可避免地至少有一个复制或移动构造函数?

我尝试的是以下内容:

class Player
{
  //...
  public:
    Player();
    Player(std::string name);
    Player& operator=(const Player&) = delete;
    Player& operator=(Player&& p) = delete;
    Player(const Player& origin) = delete;
    Player(Player&& p) = delete;

    Player getEmptyPlayer() const {
      return Player("Name");
    }
}

//in main:

Player p1("It's Me");
Player p2 = p1.getEmptyPlayer();

为什么这段代码可以编译和工作?据我了解,getEmptyPlayer() 方法实际上需要调用复制构造函数以在返回时复制对象。由于编译器提高了效率,情况并非如此,而是复制省略(NRVO)开始转向并直接在应该存在的位置构造对象并且不进行复制。尽管如此,cppreference(见上文)表示需要存在可访问或现有的复制/移动构造函数。那么这里发生了什么?

先感谢您!

4

2 回答 2

1

复制省略(NRVO)可以删除复制和移动构造函数吗?

不。

如果有副本(或移动),则类型必须是可复制的(或可移动的)。仅仅因为复制(或移动)可以被优化掉并不能使这样的程序格式良好。

为什么这段代码可以编译和工作?

因为不涉及复制(也不移动)(C++17 起)。

据我了解,getEmptyPlayer() 方法实际上需要调用复制构造函数以在返回时复制对象。

从 C++17 开始就没有了。

在 C++17 之前曾经需要它(并且可以省略调用)。

于 2020-04-09T19:17:27.963 回答
0

这个问题绝对是胡说八道。引用说“复制/移动构造函数不需要存在[...]”。

我非常抱歉没有正确阅读。

于 2020-04-09T19:18:18.473 回答