I have a class Box
, and assume that it is rather heavy weight (eg. memory intensive + dynamically allocated data). I have another class BoxWrapper
, which as the name suggests is essentially a wrapper on top of Box
. Currently, its bare-bones implementation is as follows:
class BoxWrapper
{
public:
BoxWrapper(const Box& box)
: m_Box(box)
{
}
private:
Box m_box;
};
In my application, we instantiate the Box
as a private variable and it is accessed + modified throughout the application lifetime. However, I become concerned when my application tries to construct a BoxWrapper
; clearly it performs a copy of the Box
and I’m worried about a potential performance hit since Box
can be very large.
How can I deal with this? My first thought was maybe I can add a BoxWrapper(Box&& box)
but that would mean I would need to std::forward
my box, which is not acceptable since the box will still be needed later in the application.
I come from a C background so I thought another solution would be to have BoxWrapper
store a pointer Box* m_box
instead! This would avoid a costly copy. However, since this is cpp I thought maybe I should use a smart pointer instead. Something like std::shared_ptr<Box>
seems to work. This is where I’m running into questions.
-
When I’m reading cppreference for shared_ptr, I’m having trouble understanding the various symbols. I have a basic understanding of templates, but if we’re dealing with
std::shared_ptr<T>
, then why are so manytemplate <class Y>
‘s in the picture? What doesY
mean in the context of us trying to create a pointer forT
? -
I realised that I can construct a shared pointer as so:
auto box_ptr = std::make_shared<Box>(box);
wherebox
was previously defined. I assume I can do this because of the constructor (9) from cppreferences sincebox
is an lvalue? -
Finally, I’m not even sure if shared_ptr could help me much here. If I construct a shared pointer with an lvalue, I would still be making a copy of the
Box
. I still can’t usestd::forward
as the Box cannot be moved and is still being used by the application later. Is this the correct understanding? It looks like I’m better off just using a raw pointer.