Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ smart pointer const correctness

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:

  • Store it as a shared_ptr<T> or shared_ptr<const T> inside the container?
  • OR
  • Do I change the map, vector types (e.g. insert_element(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>?

like image 368
user231536 Avatar asked Jan 17 '10 02:01

user231536


People also ask

Does C have const correctness?

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.

Why is const correctness important?

The benefit of const correctness is that it prevents you from inadvertently modifying something you didn't expect would be modified.

Can a shared pointer be const?

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.

Does using const improve performance?

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.


1 Answers

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>.

like image 72
Terry Mahaffey Avatar answered Sep 19 '22 04:09

Terry Mahaffey