C++ 调用转换函数后是否调用移动构造函数?

C++ 调用转换函数后是否调用移动构造函数?,c++,c++11,initialization,language-lawyer,c++17,C++,C++11,Initialization,Language Lawyer,C++17,考虑这个例子: struct T { }; struct S { operator T(); }; S s; T t = s; [dcl.init]将带我们到[over.match.copy],它将找到转换函数操作符T()。但是我们在那一点上完成了吗,还是必须调用T(T&&rhs),通过[dcl.init.ref]将rhs绑定到操作符T()的返回?C++11和C++1z在这个问题的答案上有什么不同吗?这属于下面的问题,重载解析选择转换函数后会发生什么非常清楚: 调用所选函数时,使用

考虑这个例子:

struct T { };

struct S {
    operator T();
};

S s;
T t = s;
[dcl.init]将带我们到[over.match.copy],它将找到转换函数
操作符T()
。但是我们在那一点上完成了吗,还是必须调用
T(T&&rhs)
,通过[dcl.init.ref]将
rhs
绑定到
操作符T()的返回?C++11和C++1z在这个问题的答案上有什么不同吗?

这属于下面的问题,重载解析选择转换函数后会发生什么非常清楚:

调用所选函数时,使用初始值设定项表达式作为其 论点如果函数是构造函数,则调用的值为 其结果对象为的目标类型的cv非限定版本 由构造函数初始化。这个电话是用来打电话的 根据上面的规则,直接初始化 复制初始化的目标

在您的情况下,这反过来又会出现:

如果初始值设定项表达式为prvalue且cv不合格 源类型的版本与 在目标中,初始值设定项表达式用于初始化 目标对象


在C++11中,第二步确实调用了移动构造函数,因为它没有对应于C++17的17.6.1的项目符号。相反:

如果初始化是直接初始化[…],则构造函数是 考虑过的。适用的构造函数 枚举([over.match.ctor]),并通过 重载解析([over.match])。这样选择的构造函数是 调用以使用初始值设定项表达式或 表达式列表作为其参数。如果没有适用的构造函数,或 重载解析不明确,初始化格式不正确

这一举措可以(实际上也将)被忽略;看


更有趣的例子是

T t(s);
在C++17语言中,调用移动构造函数实际上是必需的,因为它使用直接初始化规则,并且对
T
的构造函数进行重载解析。选择
T
的移动构造函数并调用它来初始化
T
,将
s
转换为
T
prvalue,该值被具体化为临时值并绑定到移动构造函数的参数。17.6.1项目符号在此过程中根本无法访问,C++11的[class.copy]/31(现在)中允许省略的项目符号已在C++17中删除


这很可能是一个缺陷。

我认为复制初始化需要有一个可访问的复制构造函数(对于
T
),但如果可用,将使用移动构造函数(或者完全删除副本,取决于
操作符T()
实现,它可能能够应用NRVO)。您能详细说明最后一部分吗?“为什么17.6.1不以同样的方式应用于这两种情况?”巴里详细解释道。非常感谢。一、 首先,我期待着那篇建议简化初始化的论文…@巴里,我们不是所有人。考虑到这里已经有多个初始化的帖子,所以有些甚至包含在C++ FAQ中,IMO太多了,C++ 11实际上允许在这里省略吗?由于初始化是从
S
对象到
T
对象,从
T
prvalue对象到
T&&
引用,但从来没有从
T
prvalue对象到
T
对象,因此我还不知道C++11如何允许删除移动。