为什么命名返回值优化在这里不起作用?

Zeb*_*ish 2 c++ return-value-optimization

我知道我已经删除了复制构造函数,我假设这没问题,因为我期望命名返回值优化并且会发生直接初始化。复制构造函数需要声明吗?如果我遇到了类成员也无法复制的问题,那么我该怎么办?

class UniqueBufferPointer
{public:
    UniqueBufferPointer() {}
    UniqueBufferPointer(const UniqueBufferPointer& other) = delete;
    UniqueBufferPointer(UniqueBufferPointer&& other) {}
    UniqueBufferPointer& operator=(const UniqueBufferPointer&) = delete;

};


struct GFXAPIImage
{
    GFXAPIImage() {}

    UniqueBufferPointer handle;
    GFXAPIImage(const GFXAPIImage&) = delete;
    //GFXAPIImage(const GFXAPIImage& other) = default; // If I use this instead of the compiler complaining that it can't access the copy constructor of this class, it complains it can't access the copy constructor of UniqueBufferPointer.

};


GFXAPIImage func()
{
    GFXAPIImage f;
    return f; //GFXAPIImage(const GFXAPIImage&) cannot be referenced, it is a deleted function
}


int main()
{

    GFXAPIImage f = func();
}
Run Code Online (Sandbox Code Playgroud)

我在 Visual STudio 上并使用 /O2 优化标志进行编译。

编辑:此外,如果我为 GFXAPIImage 声明一个移动构造函数,它也会编译。这是否意味着它使用移动构造函数?为什么?这是一个 l 值,不应该移动它。

YSC*_*YSC 5

命名返回值优化是一种非强制性的复制省略。这意味着返回的对象必须具有可访问的、不可删除的复制或移动构造函数。

引用cppreference.com

非强制复制/移动 (C++11 起) 省略

在以下情况下,允许但不要求编译器省略类对象的复制和移动 (C++11 起) 构造,即使复制/移动 (C++11 起) 构造函数和析构函数具有可观察端-效果。这些对象直接构造到存储中,否则它们将被复制/移动到存储中。这是一种优化:即使发生并且未调用复制/移动 (C++11 起) 构造函数,它仍然必须存在且可访问(就好像根本没有发生优化一样),否则程序会出错-形成

  • 在 return 语句中,当操作数是具有自动存储期限的非易失性对象的名称时,该对象不是函数参数或 catch 子句参数,并且与以下类型具有相同的类类型(忽略 cv 限定)函数返回类型。这种复制省略的变体称为 NRVO,“命名返回值优化”。

引用标准[class.copy.elision]/1

当满足某些标准时,实施允许实现省略复制/移动构造[...]

  • 在具有类返回类型的函数的 return 语句中,当表达式是具有自动存储持续时间的非易失性对象的名称时 [...]