I am starting using c++11 features and I like to use smart pointers only to own the objects. Here is my class:
class MyClass {
public:
vector<MyObject*> get_objs() const;
private:
vector<unique_ptr<MyObject>> m_objs;
};
The semantics is that MyClass
owns a serial of MyObject
which are created through make_unique
(). get_objs()
returns a vector of raw pointers in order for various callers to update the objects. Because those callers do not own the objects, so the function does not return vector<unique_ptr>.
But this means I need to implement get_objs()
like this:
vector<MyObjects*> MyClass::get_objs() const
{
vector<MyObjects*> ret;
for (auto obj : my_objs) {
ret.push_back(obj->get());
}
return ret;
}
My concern is get_objs()
is called fairly often, each time there is an overhead to construct this raw pointer vector.
Is there something I could do here? If there is no c++11 tricks to save the overhead, should I just use type vector<MyObject*>
for m_objs
in the first place?
UPDATE 1
Jonathan Wakely's solution using operator[]
improves mine so that caller can access individual object directly.
Is there any other solution? I do not mind go over all the places calling get_objs(),
but like to see if there is even better solution.
Another note - I cannot use BOOST, just some restriction I have to live with.
class MyClass {
public:
std::vector<std::unique_ptr<MyObject>> const& get_objs() const {
return m_objs;
}
private:
std::vector<std::unique_ptr<MyObject>> m_objs;
};
a const std::unique_ptr<MyObject>&
cannot steal ownership, and is not the same as a std::unique_ptr<const MyObject>
. A const std::vector<std::unique_ptr<MyObject>>&
can only grant const
access to its data.
In c++20 I would instead do this:
class MyClass {
public:
std::span<std::unique_ptr<MyObject> const> get_objs() const {
return {m_objs.begin(), m_objs.end()};
}
private:
std::vector<std::unique_ptr<MyObject>> m_objs;
};
which hides the implementation detail of "I am storing it in a vector" while exposing "I am storing it contiguously".
Prior to c++20, I advise finding or writing your own span
type if you have the budget. They are quite useful.
For the record, I think something like Jonathan Wakely's answer is the way to go. But since you asked for more possibilities, another one is to use shared_ptr
instead of unique_ptr
:
class MyClass {
public:
const vector<shared_ptr<MyObject>>& get_objs() const {
return m_objs;
}
private:
vector<shared_ptr<MyObject>> m_objs;
};
This improves the original code in two ways:
get_objs
; you can just return a reference to the one you have.shared_ptr
ensures the pointed-to objects aren't deleted until all references have been released.On another note, get_objs
arguably should not be const
. Calling code can't modify the vector itself, but it can modify the MyObject
s it contains.
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