共享指针和 const 正确性

Posted

技术标签:

【中文标题】共享指针和 const 正确性【英文标题】:Shared pointers and const correctness 【发布时间】:2016-03-21 11:57:30 【问题描述】:

将类的 const 正确性 扩展到其指向的成员的正确方法是什么?在示例代码中,get 方法的常量版本是要创建一个std::shared_ptr,其引用计数器与内部成员m_b 相同,还是从0 重新开始计数?

class A

    std::shared_ptr< B > m_b;

public:

    std::shared_ptr< const B > get_b( ) const
    
        return m_b;
    

    std::shared_ptr< B > get_b( )
    
        return m_b;
    

【问题讨论】:

您可能还想实现 get_const_b(),类似于标准容器 (en.cppreference.com/w/cpp/container/vector/begin) 的方法 cbegin()cend() 【参考方案1】:

shared_ptr 在您从另一个shared_ptr 构造时将始终保留引用计数; 不安全地使用它的唯一方法是从原始指针构造:shared_ptr&lt;...&gt;(my_ptr.get()) // don't do this

您可能还对 propagate_const 包装器感兴趣,它位于 Library Fundamentals TS v2 中,因此可能很快就会在您的实现中可用。

【讨论】:

【参考方案2】:

可以通过use_count()进行一些测试来推断答案。

还要注意方法解析可能不是很明显:

class B ;

class A 
  std::shared_ptr<B> m_b;

public:
  A()  m_b = std::make_shared<B>(); 

  std::shared_ptr<const B> get_b() const 
    std::cout << "const" << std::endl;
    return m_b;
  

  std::shared_ptr<B> get_b() 
    std::cout << "non const" << std::endl;
    return m_b;
  
;

int main(int, char **) 

  A a;

  std::shared_ptr<B> b = a.get_b();

  std::cout << b.use_count() << std::endl;

  std::shared_ptr<const B> cb = a.get_b();

  std::cout << cb.use_count() << std::endl;

  const A &a_const_ref = a;

  std::shared_ptr<const B> ccb = a_const_ref.get_b();

  std::cout << ccb.use_count() << std::endl;

  return 0;

输出:

non const
2
non const
3
const
4

【讨论】:

拜托,你能澄清一下这里到底什么是反直觉的,你期望什么样的陷阱?结果对我来说似乎很合乎逻辑和安全。 可以认为第二次调用get_b() 解析为const 版本。此外,第三次调用会增加相同的 ref 计数器,这就是问题本身的答案。 我稍微改写了我的答案,并不是要这么强调陷阱。 谢谢。毕竟这种方法是安全的。

以上是关于共享指针和 const 正确性的主要内容,如果未能解决你的问题,请参考以下文章

智能指针的 const 正确性

如何正确声明从非常量迭代器到指针的 const 指针

带有指针的结构的 const 正确性

const和一二级指针

constexpr 和使用重新解释强制转换的静态 const void 指针的初始化,哪个编译器是正确的?

C++ const 正确性漏洞或意外使用?