c++ - 在执行复制省略时,当移动构造函数被删除时,编译器不会在重载决策中考虑复制构造函数。为什么?

标签 c++ language-lawyer c++14 copy-elision

我可以理解编译器正在下面的代码中执行 copy-elision,因为在所谓的 copy-initialization 中没有调用复制和移动构造函数主要()。参见 live example .

#include <iostream>
struct S {
    S() = default;
    S(const S&) { std::cout << "copy ctor" << '\n'; }
    S(S&&) { std::cout << "move ctor" << '\n'; }
};

int main() {
    S s = S(); 
}

但是我无法理解为什么当我删除移动构造函数时代码无法编译,如下所示:

#include <iostream>
struct S {
    S() = default;
    S(const S&) { std::cout << "copy ctor" << '\n'; }
    S(S&&) = delete;
};

int main() {
    S s = S(); 
}

在这种情况下,我在 §12.8/32 (N4140) 中找不到任何内容禁止使用或省略复制构造函数。这是§12.8/32中引起我注意的句子,这似乎表明复制构造函数应该在重载决议中被考虑:

If the first overload resolution fails or was not performed, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue.

编辑

来自 T.C. 的评论之一下面,我了解到当要复制的对象由右值指定时,根据§12.8/32,编译器不会将复制构造函数视为复制的候选者,即使复制无论如何都会被省略.也就是说,最终结果将是使用默认构造函数构造对象 s。相反,在这种情况下,标准要求(哪里??)代码格式错误。除非我对这个方案的理解是完全错误的,否则这对我来说没有任何意义。

最佳答案

这与复制省略或构造函数无关;这只是重载决议。

如果我们有一对重载:

void f( T&& rv );
void f( const T& lv );

那么重载解析规则表明 f( T{} ) 更适合 f(T&&)

复制省略可以省略复制或移动,但前提是代码定义明确(即使编译器选择不实现复制省略)。您的代码定义不明确,因为它指定调用已删除的函数。

关于c++ - 在执行复制省略时,当移动构造函数被删除时,编译器不会在重载决策中考虑复制构造函数。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31775876/

相关文章:

c++ - 据我所知,根据 C++14 中的 §5.19/3 和 §5.19/2,这段代码不应该编译

c++ - 三个 std::complex 特化和 noexcept

c++ - C++ 中 class = void 的用途?

c++ - 为容器生成成员类型

c++ - 更改 mex 函数中的常量参数

c++ - 是什么导致使用三元而不是短裤将这个有符号整型转换为无符号整型?

c++ - 模板的合格和不合格名称查找的不同行为

c++ - Release模式下的访问冲突

c++ - 为什么仅仅因为有一个用户定义的析构函数,复制构造函数就不是微不足道的了?

c++ - 当前草案是否允许形成由两个非静态成员声明组成的重载集,其中一个具有引用限定符