0

I'm trying to understand how can I substitute raw pointers on my C++ software with smart-pointers.

I have the following code:

class Foo { private: std::vector<Bar *> m_member; }; 

Now in some function I populate that vector with:

m_member.push_back( new Bar() ); 

and when my program finishes I delete the memory with:

for( std::vector<Bar *>::iterator it = m_member.begin(); it < m_member.end(); ++it ) { delete (*it); (*it) = NULL; } 

Now all this is good.

The problem is as I see it comes from the fact that at one point of time I may need to delete one of the member from the vector (this member is user-specified).

Now this is easy:

for(...) { if( (*it)->GetFieldFromBar() == <user_specified_condition> ) { delete (*it); (*it) = NULL; } } 

But how do I re-write it with the smart pointers? Is it even possible?

3
  • 3
    What have you tried? It should be pretty easy to change std::vector<Bar *> m_member; to std::vector<std::unique_ptr<Bar>> m_member;. Then if you need to delete an element you just erase it. Commented Feb 6, 2019 at 21:06
  • (I would actually use unique_ptr and not shared_ptr in this case). Commented Feb 6, 2019 at 21:07
  • 4
    Why pointers at all, would std::vector<Bar > not suffice? Commented Feb 6, 2019 at 21:18

2 Answers 2

3

It's actually far easier with smart pointers, and here unique_ptr.

Population is done through:

m_member.push_back(std::make_unique<Bar>()); // C++14, you can use std::unique_ptr<Bar>(new Bar) is you only have C++11 

No need for a destructor.

For custom deletion:

for(auto& p: m_member) { if( p->GetFieldFromBar() == <user_specified_condition> ) { p.reset(); } } 
Sign up to request clarification or add additional context in comments.

5 Comments

Just to point out, std::make_unique is a c++14 function.
@AdamBrinded Very good point. I thought about it and forgot to add it.
It’s worth checking however, if your compiler(s) for a particular project support make_unique in c++11. If it does then make_unique is probably preferable.
And custom deletion might use erase-remove idiom now :)
@Jarod42 Depends, OP doesn't seem to want to remove the entry itself. At least not in what he showed us.
0

Yes, using std::vector<std::unique_ptr<Bar>> is ideal in this case. You clearly have ownership in the vector.

Adding elements to it can be done the following in c++14:

m_member.push_back( std::make_unique<Bar>() ); 

Removing all elements gets reduced to: m_member.clear() or even just letting it go out of scope.

Selectively removing the elements is better done like:

m_member.erase(std::remove_if(m_member.begin(), m_member.end(), [&](auto &&ptr) { return ptr->GetFieldFromBar() == <user_specified_condition>; }), m_member.end()); 

A bit descriptive for dealing with all elements, though, you can wrap it in a function to get rid of the boiler plate.

2 Comments

the question is marked with c++11, not c++14. Does this mean that the constructor will be m_member.push_back( std::unique_ptr<Bar>( new Bar() ) )?
Or emplace_back(new Bar()); unless you use libraries like absail or your STL exposes this also in c++11 mode

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.