当我不移动任何东西时,为什么 clang 会抱怨已删除的移动 ctor?

Why does clang complain about a deleted move ctor when I don't move anything?

前提 :

#include <iostream>
using namespace std;

class ABC {
 public:

   ABC() {
     cout << "Default constructor ..\n";
   }

   ABC(const ABC& a) {
     cout << "In copy constrcutor ..\n";
   }
   ABC(ABC&& aa) = delete;
};

int main(int argc, char* argv[]) {
  ABC b{ABC{}};
  return 0;
}

用 GCC 和 Clang 编译这个

Clang - Apple LLVM version 8.1.0 (clang-802.0.42)

Gcc - 5.4.0 ubuntu

观察 Clang 抱怨删除了 Move 构造函数。

Gcc 一点也不抱怨。并且会正确输出。

问题为什么?

对于 gcc,我知道如果您只是简单地同时初始化左值和右值,它会优化并且不会实际调用复制构造函数并将临时值复制到左值。

为什么 Clang 不同? 我认为(不确定,因此问题)这是 C++ 标准,哪个偏离(或不偏离)?还是我哪里做错了。

编译命令 : g++ --std=c++11 -O3 file.cpp

为了获得更多乐趣,请删除花括号并用括号代替 ;)

ABC b{ABC{}};ABC b(ABC());,与此问题无关。

EDIT :有人将问题标记为重复问题,但事实并非如此。我明确表示我认为 C++11 标准包括复制省略。然而,CLANG 在像构造函数这样关键的东西上似乎没有相同的行为。

这里是 LINK : http://en.cppreference.com/w/cpp/language/copy_elision

很明显,它说的是 C++11。我信任 cppref.

ABC{} 是临时的,因此 ABC b{ABC{}} 将使用移动构造函数(即使可以省略)。

由于移动构造函数被删除,您应该得到一个错误。

您的 gcc 版本有错误,无法通过错误的省略检测到错误。

在 C++17 中,通过保证复制省略,甚至可以省略已删除的构造函数。因此,您的代码将在 C++17 中编译,仅调用一个默认构造函数。

EDIT : Someone marked the question as a dup, which it is not. I clearly state that I think C++11 standard includes copy elision. However, CLANG does not seem to have the same behavior on something as critical as constructors.

HERE Is the LINK : http://en.cppreference.com/w/cpp/language/copy_elision

clearly, it says C++11. I trust cppref.

是我把它标记为骗子的。从您链接的页面:

Under the following circumstances, the compilers are permitted, but not required to omit the copy- and move- (since C++11)construction

When a nameless temporary, not bound to any references, would be copied or moved (since C++11) into an object of the same type (ignoring top-level cv-qualification), the copy/move (since C++11) is omitted. (until C++17)

This optimization is mandatory; see above. (since C++17)

如您所见,移动构造函数将是必需的,因为复制省略不是必需的,而是建议 C++17 之前的版本。 C++17 编译器不应该在相同情况下抱怨删除移动构造函数。