c++ - 调用转换函数后是否调用了移动构造函数?

标签 c++ c++11 initialization language-lawyer c++17

考虑这个例子:

struct T { };

struct S {
    operator T();
};

S s;
T t = s;

[dcl.init] 将带我们到 [over.match.copy],它将找到转换函数 operator T()。但是我们是否已经完成了,还是我们必须调用 T(T&& rhs),将 rhs 绑定(bind)到 operator T() 的返回> 通过 [dcl.init.ref]? C++11和C++1z对于这个问题的答案有什么不同吗?

最佳答案

这属于 [dcl.init]/17.6.3 ,这很清楚重载决议选择转换函数后会发生什么:

The function selected is called with the initializer expression as its argument; if the function is a constructor, the call is a prvalue of the cv-unqualified version of the destination type whose result object is initialized by the constructor. The call is used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.

在您的情况下,这又会递归到 [dcl.init]/17.6.1 :

If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object.


在 C++11 中,第二步确实调用了移动构造函数,因为它没有对应于 C++17 的 17.6.1 的项目符号。而是 you do the direct-initialization/overload resolution dance again :

If the initialization is direct-initialization, [...], constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one is chosen through overload resolution ([over.match]). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.

这个 Action 可以(并且实际上会)被省略;见 [class.copy]/31 .


更有趣的案例其实是

T t(s);

根据 C++17 的措辞,实际上 需要调用移动构造函数,因为它使用直接初始化规则并在 T 上进行重载解析构造函数。选择 T 的移动构造函数并调用它来初始化 t,将 s 转换为 T 纯右值,即具体化为一个临时的并绑定(bind)到移动构造函数的参数。在此过程中根本无法访问 17.6.1 项目符号,并且 C++11 的 [class.copy]/31(现为 [class.copy.elision]/1 )中允许在这种情况下省略的项目符号在 C++17 中被删除。

这很可能是一个缺陷。

关于c++ - 调用转换函数后是否调用了移动构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44311306/

相关文章:

python - 创建不同类的类实例的更有效方法?

c++ - Win32 工具栏下拉按钮消息处理

c++ - 保护 QML 源代码免遭抄袭

c++ - c 遗留代码给我左侧的指针;需要正确错误的积分值

c++ - 在 C++ 中使用 initializer_list 进行结构赋值

C++ 测验 : Display Answer Choices with Vector Correct Cycling

c++ - C++ 11 auto关键字多少太多了?

c++ - 如何在 C++ 中访问成对集合

C99 结构指定初始化器和其他值

c++ - "weird"变量初始化