【问题标题】:Dereferencing a temporary pointer to initialize a reference member variable取消引用临时指针以初始化引用成员变量
【发布时间】:2021-03-12 22:33:47
【问题描述】:

我正在使用可以容纳大型数据结构的外部库。调用它返回指向它管理的对象的指针:

class ExternalLib {
public:
  int* GetLargeObject() { return &large_object; };

private:
  int large_object = 1;
};

我正在尝试为这个外部库编写一个包装器,它可以保存对我感兴趣的大型数据结构的 const 引用:

class ExternalLibraryWrapper {
public:
  ExternalLibraryWrapper() : large_object_ref(*ext.GetLargeObject()){};

private:
  ExternalLib ext;
  const uint &large_object_ref;
};

但是,我收到编译器警告:

引用成员 'large_object_ref' 绑定到一个临时对象,其生命周期将比构造对象的生命周期短 [clang: dangling_member]

据我了解,ext.GetLargeObject() 返回一个指向(*this).ext.large_object 地址的临时指针。编译器不应该知道构造的对象&large_object_ref 实际上并没有绑定到临时对象吗?

【问题讨论】:

  • 我认为问题在于您试图将 const 引用存储到不是 const 的东西开始,因此编译会创建一个临时来满足绑定。这将解释警告。为什么你需要存储参考?简单地存储原始指针并按原样使用它有什么问题? class ExternalLibraryWrapper { public: ExternalLibraryWrapper() : large_object_ptr(ext.GetLargeObject()){}; private: ExternalLib ext; int *large_object_ptr; };
  • 这在我看来基本上是粗略的。您正在使用初始化列表中的另一个成员,假设该对象已经构造。情况可能并非如此,这可能是编译器以迂回方式发出此警告的原因。
  • 共享指针仅应在共享对象所有权时使用。这不是这里的情况。 large_object 的所有权定义明确。是否应该按照他们的方式定义是另一回事。
  • @paddy 我故意对成员变量进行排序,以便在分配large_object_ref 之前构造ext
  • @RemyLebeau:添加const 不应导致临时实现!我们一直通过 const-reference 接受参数而不期望副本。我的水晶球说实际代码中存在类型不匹配,允许隐式转换——或者编译器错误。

标签: c++ pointers reference c++17 lifetime


【解决方案1】:

当初始化器是 prvalue 或初始化器的类型 不同于 与引用的类型 more 比 cv-qualifiers 但可以转换为它(当然,除非转换是用户定义的并产生引用)。 (这种情况在左值引用非常量的情况下被拒绝;const U& 情况由于历史原因被接受。从一开始就拥有const T&& 并拥有 it会更好> 意思是“你可以通过临时的,我不会修改你通过的任何东西”,但这不是我们现在的情况。)

显然取消引用 pointer 会产生一个左值,因此这个警告(非常有用,因为不可能使用如此初始化的引用!)表明类型不匹配与您的情况有关。

【讨论】:

    猜你喜欢
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 2020-11-10
    • 1970-01-01
    相关资源
    最近更新 更多