c++ - MSVC 无法返回可以复制但不能移动的对象

标签 c++ visual-c++ c++17 language-lawyer copy-elision

在摆弄复制省略时,我遇到了这种奇怪的行为:

class Obj {
 public:
  Obj() = default;

  Obj(Obj&&) = delete;
  Obj(const Obj&) { std::cout << "Copy" << std::endl; }
};

Obj f1() {
  Obj o;
  return o; // error C2280: move constructor is deleted
}

Obj f2() {
  Obj o;
  return Obj(o); // this however works fine
}

int main() {
  Obj p = f1();
  Obj q = f2();

  return 0;
}
GCC 和 Clang 接受此代码并且能够在两种情况下使用复制省略。
f1() MSVC 提示无法返回 o因为 Obj 的移动构造函数被删除。但是,我希望它能够依靠复制构造函数。 这是 MSVC 中的错误还是这种期望的行为(我不明白)和 GCC/Clang 是否过于宽容?
如果我提供移动构造函数,MSVC 能够在编译为 Release 时省略移动。
有趣的是 MSVC 能够编译 f2() .据我所知,这是由于返回构造函数调用的结果时强制复制省略。然而,我只能返回 o 感觉违反直觉。如果我手动复制它,则按值。
我知道这种情况可能与实际使用无关,因为可复制对象通常也是可移动的,但我对底层机制感兴趣。
以下是在线测试示例:https://godbolt.org/z/sznds7

最佳答案

f1() 上缺少错误是 clang 和 gcc 中的一个错误。 It is fixed in clang's tip-of-trunk.f1()不符合强制复制省略的条件。
删除的函数参与重载决议。如果它们被选为最佳重载,则程序格式错误。在 f1() ,被删除的移动构造函数由重载决议选择。
f2() , as of C++17, copy/move elision is guaranteed ,因此未完成移动/复制构造函数的重载解析。在 C++11/14 中,f2()也是一个错误(与 f1() 相同的错误),因为不能保证复制/移动省略。
另请参阅此指南:Never delete the special move members ,不可否认,它是在 C++17 之前编写的。

关于c++ - MSVC 无法返回可以复制但不能移动的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66404418/

相关文章:

c++ - 函数没有导致错误,但它不会返回到程序

c++ - 如何在 2 个 int 函数之间重复抛出一个变量?

C++ 字段的复制省略

c++ - 指向 void* 的类指针

c++ - 为什么我会收到以下错误 : In constructor 'B::B(int, int)' : no matching function for call to 'A::A()'

c++ - C/C++ time_t(以微秒为单位)

winforms - 当我在 C++ Windows 窗体应用程序中添加 .settings 文件时,Visual Studio 崩溃

visual-c++ - 如何从 C++ 代码访问 $(SolutionDir) 宏

c++ - 从临时返回按值 string_view 时,有没有办法获得编译器警告?

c++ - 在 C++ 中是否存在 std::conditional 的惰性等效项?