C ++智能指针const正确性

我在一个类中有几个容器,例如vector或map,其中包含shared_ptr到堆中的对象。

例如

template <typename T> class MyExample { public: private: vector<tr1::shared_ptr<T> > vec; map<tr1::shared_ptr<T> , int> h; }; 

我想有一个这个类的公共接口,它有时返回给const对象(通过shared_ptr<const T> ),有时返回shared_ptr<T>我允许调用者mutate对象。 我想要逻辑常量的正确性,所以如果我标记一个方法为const,它不能改变堆上的对象。

问题:

1)我对tr1::shared_ptr<const T>tr1::shared_ptr<T>的可交换tr1::shared_ptr<const T>困惑。 当有人将shared_ptr<const T> shared_ptr传递给类时,是否将其作为shared_ptr<T>shared_ptr<const T>在vector和map中,或者是否更改map,vectortypes(例如insert_elemeent( shared_ptr<const T> obj)?

2)更好的实例化类如下: MyExample<const int> ? 这似乎过分限制,因为我永远不会返回一个shared_ptr<int>

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 } 

编译通过

cl / EHsc f.cpp

你也可以重载一个基于const的函数。 你可以结合做这两个事实做你想做的事情。

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

我会build议以下的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); } }; 

这确保了const正确性。 就像你看到add()方法不使用<const T>而是<T>,因为你打算让类存储Ts而不是const Ts。 但是在访问它时const,你返回<const T>这是没有问题的,因为shared_ptr <T>可以很容易地转换为shared_ptr <const T>。 并且sice中的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); } }; 

如果有人向你传递了一个shared_ptr<const T>你永远不能修改T 当然,在技术上可以将const T转换为T ,但是打破了T const的意图。 所以,如果你希望人们能够添加对象到你的类,他们应该给你shared_ptr<T>和没有shared_ptr<const T> 。 当你从你的类返回的东西你不想修改,那就是当你使用shared_ptr<const T>

shared_ptr<T>可以被自动转换(不经过明确的转换)到一个shared_ptr<const T>但不能shared_ptr<const T> 。 它可以帮助你(无论如何你都应该这样做)自由地使用const方法。 当你定义一个类方法const ,编译器不会让你修改你的任何数据成员,或者返回除const T以外的任何东西。 所以使用这些方法可以帮助你确定你没有忘记什么,并且会帮助你的class级的用户理解这个方法的意图是什么。 (例如: virtual shared_ptr<const T> myGetSharedPtr(int index) const;

你的第二条语句是正确的,你可能不希望将你的类实例化为<const T> ,因为你将永远无法修改你的任何T

有一点要认识到的是:

tr1::shared_ptr<const T>模仿T const *的function,即它指向的是const,但指针本身不是。

所以你可以给你的共享指针分配一个新的值,但是我希望你不能使用解引用的shared_ptr作为l值。