I have a few containers in a class, for example, vector or map which contain shared_ptr's to objects living on the heap.
For example
template <typename T> class MyExample { public: private: vector<shared_ptr<T> > vec_; map<shared_ptr<T>, int> map_; };
I want to have a public interface of this class that sometimes returns shared_ptrs to const objects (via shared_ptr<const T>
) and sometimes shared_ptr<T>
where I allow the caller to mutate the objects.
I want logical const correctness, so if I mark a method as const, it cannot change the objects on the heap.
Questions:
1) I am confused by the interchangeability of shared_ptr<const T>
and shared_ptr<T>
. When someone passes a shared_ptr<const T>
into the class, do I:
shared_ptr<T>
or shared_ptr<const T>
inside the container? shared_ptr<const T>
obj)? 2) Is it better to instantiate classes as follows: MyExample<const int>
? That seems unduly restrictive, because I can never return a shared_ptr<int>
?
In C, C++, and D, all data types, including those defined by the user, can be declared const , and const-correctness dictates that all variables or objects should be declared as such unless they need to be modified.
The benefit of const correctness is that it prevents you from inadvertently modifying something you didn't expect would be modified.
boost::shared_ptr<Bar const> prevents modification of the Bar object through the shared pointer. As a return value, the const in boost::shared_ptr<Bar> const means that you cannot call a non-const function on the returned temporary; if it were for a real pointer (e.g. Bar* const ), it would be completely ignored.
const correctness can't improve performance because const_cast and mutable are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const data may e.g. be a pointer to a std::atomic , meaning the compiler has to respect changes made by other threads.
shared_ptr<T>
and shared_ptr<const T>
are not interchangable. It goes one way - shared_ptr<T>
is convertable to shared_ptr<const T>
but not the reverse.
Observe:
// 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 }
compile via
cl /EHsc f.cpp
You can also overload a function based on a constness. You can combine to do these two facts to do what you want.
As for your second question, MyExample<int>
probably makes more sense than MyExample<const int>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With