共享指针和const正确性

8

如何正确地将类的常量性扩展到其指向的成员变量?在示例代码中,get方法的常量版本是否会创建一个引用计数与内部成员变量m_b相同的std::shared_ptr,还是从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(),类似于标准容器的 cbegin()cend() 方法(http://en.cppreference.com/w/cpp/container/vector/begin)。 - filipos
2个回答

7
shared_ptr 在从另一个 shared_ptr 构造时始终会保留引用计数;唯一不安全的使用方式是从原始指针构造:shared_ptr<...>(my_ptr.get()) // 不要这样做
您可能还对 propagate_const 包装器感兴趣,它在 Library Fundamentals TS v2 中,因此很快可能会在您的实现中提供。

0

可以通过使用 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

请问,您能否澄清这里到底有什么反直觉的地方,以及您预期会遇到什么陷阱?在我看来,结果似乎非常合乎逻辑和安全。 - filipos
有人可能认为第二次调用 get_b() 解析到了 const 版本。此外,同一个引用计数器被第三次调用增加,这也是问题的答案。 - Emerald Weapon
我稍微改了一下我的回答,不是想过多强调陷阱。 - Emerald Weapon
谢谢。毕竟这种方法是安全的。 - filipos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接