即使删除了复制构造函数,C++ 变量也会初始化

问题描述 投票:0回答:1

下面的代码出乎意料地有效!

class CameraBuffer;
class CameraBufferAccessor{
  friend CameraBuffer;
  private:
    CameraBufferAccessor(const int &data, const int &mutex);
  public:
    CameraBufferAccessor() = default;
    CameraBufferAccessor(const CameraBufferAccessor &) = delete;
    CameraBufferAccessor(CameraBufferAccessor &&) = delete;
    void operator=(const CameraBufferAccessor &other) = delete;
    void operator=(CameraBufferAccessor &&other) = delete;
};
class CameraBuffer {
  public:
    const CameraBufferAccessor getReadAccess() const {
        return {1, 2};
    }
};
int main() {
    auto buffer = CameraBuffer();
    CameraBufferAccessor a = buffer.getReadAccess();
    CameraBufferAccessor b = a;

这里

CameraBufferAccessor b = a;
正如预期的那样抛出错误,因为复制构造函数被显式删除。

但是发生了一些我没有预料到的事情,我一直在寻找它,到目前为止还没有解释。 尽管

CameraBufferAccessor a = buffer.getReadAccess();
行使用了一个函数,但它仍然可以工作 具有非引用返回,其本身应该使用复制构造函数,其次返回的
CameraBufferAccessor
应复制到
a
再次使用复制/移动构造函数初始化
a
,但它会编译并且不会抛出.

我听说出于优化目的的编译器可以在必要时绕过复制构造, 如果是这种情况,我该如何判断编译器何时这样做?

我以为是因为

getReadAccess
的返回语句中的大括号直接初始化了返回值,所以我尝试了
return CameraBufferAccessor(1, 2)
;但它仍然有效。也许编译器优化?

c++ c++11 constructor compiler-errors initialization
1个回答
0
投票

这是一个非常棘手的问题,但我想我有答案。

您不希望用户初始化

CameraBufferAccessor
,因此您创建了私有构造函数、默认构造函数和复制构造函数。为了进行测试,您删除了除私有构造函数之外的所有构造函数:
CameraBufferAccessor(const int &data, const int &mutex);
。因此,当您尝试使用
CameraBufferAccessor a = buffer.getReadAccess();
进行初始化时,您将其传递给朋友静态类,并且静态方法可以访问私有构造函数:

class CameraBuffer {
public:
    const CameraBufferAccessor getReadAccess() const {
        return {1, 2};
    }
};

在这里加好友:

class CameraBufferAccessor{
friend CameraBuffer;
//...

我希望我能帮助您更好地理解为什么可以访问构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.