0
votes

I have a map of auto_ptr's and I am simply trying to set and get map elements but its producing compiler errors. I don't understand what the compiler error means and whats going wrong?

Get compiler error:

[Error] passing 'const std::auto_ptr' as 'this' argument of 'std::auto_ptr<_Tp>::operator std::auto_ptr_ref<_Tp1>() [with _Tp1 = int; _Tp = int]' discards qualifiers [-fpermissive]

Set compiler error:

[Error] no match for 'operator=' (operand types are 'std::map, std::auto_ptr >::mapped_type {aka std::auto_ptr}' and 'int*')

Also I've heard it's not advised to use auto_ptr's in standard c++ library collections (list, vector, map). What kind of smart pointer should I use in the below code?

std::map <std::string, std::auto_ptr<int> > myMap;

// Throws compiler error
std::auto_ptr <int> a = myMap["a"];
// Also throws compiler error
myMap["a"] = new int; 
1
Use unique_ptr. auto_ptr will be removed from C++ soon.chris
@chris unique_ptr doesn't work here either (it has deleted copy-assignment)M.M
@MattMcNabb, Good point, you can't do the first one (the second should be fine). At that point, it's a question of whether you want to share ownership with the map or take ownership from it.chris
@MattMcNabb: unique_ptr may be a reasonable choice, but std::auto_ptr <int> a = myMap["a"]; should then be updated to e.g. const std::auto_ptr<int>& a = myMap["a"];, and similarly changes to the pointer should be made using the unique_ptr API: myMap["a"].reset(new int);. shared_ptr's another alternative....Tony Delroy

1 Answers

5
votes

Firstly, don't use auto_ptr. It has broken semantics and is deprecated. The proper pointer for single-ownership semantics is unique_ptr.

You can have:

std::map<std::string, std::unique_ptr<int> > myMap;

Now, when you write myMap["a"], an entry in the map will be created for "a", and this returns a reference to that. The entry created is std::unique_ptr<int>{} which is a "null" pointer.

You can make this point somewhere, however you use the member function reset for that, not the assignment operator:

myMap["a"].reset( new int{5} );

or alternatively, since C++14,

myMap["a"] = std::make_unique<int>(5);

Your other doesn't quite make sense, if you want single ownership. You can either look at the raw pointer value, or you can take ownership. To take ownership:

std::unique_ptr<int> new_owner = std::move(myMap["a"]);

which will leave the existing map entry as a "null" pointer again, and new_owner has ownership.

If you just want to do something with the raw pointer in the map then you can use get() to get that pointer, or use the dereference operator directly on the unique_ptr:

myMap["a"].reset( new int{5} );
int *raw = myMap["a"].get();
*myMap["a"] = 6;