返回不可复制常量值的函数的不直观RVO?

考虑以下 C++ >=17 中的示例代码:

struct A{
    A() = default;
    A(const A&) = delete;
};

const A f(){ return A{}; }

int main(){
    const A& a = f(); // OK
    // A& b = f();    // Error: cannot convert 'const A' to 'A&'
    const A c = f();  // OK: Copy elision
    A d = f();        // OK!?
}

该类A是不可复制的,但由于强制复制省略,我们可以将 的结果f()放入变量中。根据cppreference.com 中的这个页面,上述行为是完全合法的,因为它指定const在发生复制省略时忽略返回值上的量词。

然而,这种行为对我来说似乎非常违反直觉。由于A是不可复制的,我觉得应该没有办法const A变成A(除非你有A::A(const A&&)构造函数)。这是一个深思熟虑的决定,还是被认为是语言规范中的缺陷?

(我在尝试实现我自己的类型擦除类时遇到了这个问题。我const在函数的返回值上指定的全部目的f()是为了防止用户获得const对象的非左值引用,但这个规范似乎开个洞。)

编辑:这个例子可能更清楚地展示了反直觉:让我们考虑一个A可移动但不可复制的类。

struct A{
    A() = default;
    A(const A&) = delete;
    A(A&&) = default;
};

int main(){
    // C++14: move / C++17: copy elision
    A a = A{}; 

    // C++14: error (deleted copy constructor) / C++17: copy elision(!!)
    A b = static_cast<const A>(A{}); 
}

这不会在 C++ <=14 中编译,但在 C++ >=17 中编译。在类可移动但不可复制的常见情况下,const这意味着在 C++14 之前无法从中获取非常量对象,但现在不再如此(只要将const其添加到纯右值中) .

以上是返回不可复制常量值的函数的不直观RVO?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>