C++智能指针const正确性

use*_*536 42 c++ const shared-ptr

我在类中有一些容器,例如vector或map,它包含生活在堆上的对象的shared_ptr.

例如

template <typename T>
class MyExample
{
public:

private:
    vector<shared_ptr<T> > vec_;
    map<shared_ptr<T>, int> map_;
};
Run Code Online (Sandbox Code Playgroud)

我希望有一个这个类的公共接口,有时会将shared_ptrs返回给const对象(via shared_ptr<const T>),有时shared_ptr<T>我允许调用者改变对象.我想要逻辑const正确性,所以如果我将方法标记为const,它就不能更改堆上的对象.

问题:

1)我对shared_ptr<const T>和的可互换性感到困惑shared_ptr<T>.当有人经过一个shared_ptr<const T>shared_ptr的进级,做我把它存储为一个shared_ptr<T>shared_ptr<const T>载体内,映射或修改我的地图,矢量类型(例如insert_elemeent(shared_ptr<const T>OBJ)?

2)如下实例化类更好MyExample<const int> 吗?这看起来过于严格,因为我永远无法回归shared_ptr<int>

Ter*_*fey 37

shared_ptr<T>shared_ptr<const T>不是可以互换的.这是一种方式 - shared_ptr<T>可转换为shared_ptr<const T>但不是相反的.

注意:

// f.cpp

#include <memory>

int main()
{
    using namespace std;

    shared_ptr<int> pint(new int(4)); // normal shared_ptr
    shared_ptr<const int> pcint = pint; // shared_ptr<const T> from shared_ptr<T>
    shared_ptr<int> pint2 = pcint; // error! comment out to compile
}
Run Code Online (Sandbox Code Playgroud)

编译通过

cl/EHsc f.cpp

您还可以基于常量重载函数.你可以结合起来做这两件事来做你想做的事.

至于你的第二个问题,MyExample<int>可能更有意义MyExample<const int>.


mmm*_*mmm 12

我建议以下的methotology:

template <typename T>
class MyExample
{
  private:
    vector<shared_ptr<T> > data;

  public:
    shared_ptr<const T> get(int idx) const
    {
      return data[idx];
    }
    shared_ptr<T> get(int idx)
    {
      return data[idx];
    }
    void add(shared_ptr<T> value)
    {
      data.push_back(value);
    }
};
Run Code Online (Sandbox Code Playgroud)

这确保了正确性.就像你看到add()方法不使用<const T>而是<T>,因为你打算让类存储Ts而不是const Ts.但是当访问它时,返回<const T>这是没有问题的,因为shared_ptr <T>可以很容易地转换为shared_ptr <const T>.并且两个get()方法都会在内部存储中返回shared_ptr的副本,调用者不会意外地更改内部指针指向的对象.这与非智能指针变体完全相同:

template <typename T>
class MyExamplePtr
{
  private:
    vector<T *> data;

  public:
    const T *get(int idx) const
    {
      return data[idx];
    }
    T *get(int idx)
    {
      return data[idx];
    }
    void add(T *value)
    {
      data.push_back(value);
    }
};
Run Code Online (Sandbox Code Playgroud)


Soa*_*Box 6

如果有人通过你,shared_ptr<const T>你就永远无法修改T.当然,技术上可以将其转换const T为a T,但这打破了制作它的意图T const.因此,如果您希望人们能够向您的班级添加对象,他们应该给您shared_ptr<T>而不是shared_ptr<const T>.当你从班级中归还你不需要修改的东西时,那就是你使用的时候shared_ptr<const T>.

shared_ptr<T>可以自动转换(没有显式转换)到一个shared_ptr<const T>但不是相反的方式.它可以帮助你(无论如何你应该这样做)自由地使用const方法.定义类方法时const,编译器不允许您修改任何数据成员或返回除a之外的任何内容const T.因此,使用这些方法可以帮助您确保不会忘记某些内容,并且可以帮助您的班级用户了解该方法的用途.(实施例:virtual shared_ptr<const T> myGetSharedPtr(int index) const;)

你的第二个陈述是正确的,你可能不想将你的类实例化<const T>,因为你永远无法修改你T的任何一个.


Eva*_*ran 3

需要认识到的一件事是:

tr1::shared_ptr<const T>T const *正在模仿它所指向的内容是 const 的功能,但指针本身不是。

因此,您可以为共享指针分配一个新值,但我希望您无法将取消引用的值用作shared_ptr左值。