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值。