I am trying to transfer the ownership of a already-defined std::unique_ptr
to the member of a class object:
#include <iostream>
#include "memory"
// base class
class base
{
public:
void setVal(int val)
{
m_val = val;
}
int getVal()
{
std::cout << "base val = " <<m_val<<std::endl;
return m_val;
}
private:
int m_val = 0;
};
// derived class
class derived1: public base
{
private:
};
// derived class
class derived2: public base
{
public:
private:
};
class user
{
public:
user(std::unique_ptr<base> d)
{
// m_class = static_cast<std::unique_ptr<base>>(d.get());
// m_class = std::make_unique<base>();
m_class = std::move(d);
}
user(std::unique_ptr<derived1> d)
{
// m_class = static_cast<std::unique_ptr<derived1>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
user(std::unique_ptr<derived2> d)
{
// m_class = static_cast<std::unique_ptr<derived2>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
void setVal(int val)
{
m_class->setVal(val);
}
int getVal()
{
return m_class->getVal();
}
private:
std::unique_ptr<base> m_class;
};
int main()
{
std::unique_ptr<base> b = std::make_unique<base>();
std::unique_ptr<base> d1 = std::make_unique<derived1>();
std::unique_ptr<base> d2 = std::make_unique<derived2>();
user ud1(std::move(d1));
user ud2(std::move(d2));
ud2.setVal(90);
ud1.setVal(10);
ud2.getVal();
ud1.getVal();
return 0;
}
It seems I std::move
d the pointer twice; first time being passing the std::unique_ptr
d1
and d2
to the constructor of user
object; second time being std::move
the d1
or d2
into member variable m_class
.
It does not feel intuitive to std::move
the pointer twice to eventually transfer the ownership of d1
and d2
to m_class. Am I doing this right, or there is a right/better way to do it? Thanks!!
Am I doing this right, or there is a right/better way to do it?
It is correct to move it twice, since you are transferring the value between three different variables.
It's also not a problem. std::move
is a compile-time cast. Calling it twice has no performance implications.
However...
You should be using member initializer lists.
user(std::unique_ptr<base> d)
: m_class{ std::move(d) }
{
}
And these constructors are superfluous. Delete them. You don't need to account for every possible derived type, they can all implicitly convert to std::unique_ptr<base>
.
user(std::unique_ptr<derived1> d)
{
// m_class = static_cast<std::unique_ptr<derived1>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
user(std::unique_ptr<derived2> d)
{
// m_class = static_cast<std::unique_ptr<derived2>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}