我有一个带有私有构造函数和公共CreateEntity函数的Entity类。CreateEntity堆栈分配新实体。在我的应用程序中,我想使用一个指向返回实体的唯一指针。我找到了一个具有临时唯一指针和两条移动指令的解决方案。如何使用make_unique和单个move指令来编写Start((中的两行?
class Entity
{
public:
Entity(const Entity&) = delete;
Entity& operator=(const Entity&) = delete;
Entity(Entity&&) = default;
Entity& operator=(Entity&&) = default;
static Entity CreateEntity();
private:
Entity(id_t id): m_ID(id) {}
private:
uint32_t m_ID;
};
Entity Entity::CreateEntity()
{
static id_t currentID = 0;
return Entity{currentID++};
}
struct Lucre : public Application
{
bool Start();
std::unique_ptr<Entity> m_Object;
}
bool Lucre::Start()
{
std::unique_ptr<Entity> ptr( new Entity(std::move(Entity::CreateEntity())));
m_Object = std::move(ptr);
}
您可以像这样组合Lucre::Start()
中的两行:
m_CameraObject.reset( new Entity( Entity::CreateEntity() ) );
这里,Entity::CreateEntity()
的返回被移动,但不需要std::move()
,因为返回已经是prvalue。
只是复制所示行的行为:
m_CameraObject = std::make_unique<Entity>(Entity::CreateEntity());
这将执行Entity
的单移动构造和std::unique_ptr
的单移动指派(假设m_CameraObject
是类型std::unqiue_ptr<Entity>
(,此外还执行Entity
和std::unqiue_ptr
的非移动/复制对象构造(在C++17或更高版本中保证,否则可能(。
由于Entity::CreateEntity()
和std::make_unique<Entity>(Entity::CreateEntity())
都已经是prvalue,因此在此不需要std::move
。在您的原件中,Entity::CreateEntity()
周围的std::move
也是多余的。
然而,如果没有完整的代码,很难判断这是否是你真正想要做的。也许让工厂函数直接返回std::unique_ptr<Entity>
是更好的选择。那么就不需要为Entity
调用move构造函数了。
我可能没有正确理解您的需求,但下面的示例代码:
- 还实现了
Entity
对象,使每个实例都有不同的ID - 仍然隐藏
Entity
类的实现细节。之前,您使用auto e = Entity::CreateInstance();
创建了一个Entity
对象。现在,您可以对auto e = Entity{};
执行同样的操作。也就是说,在这两种情况下,用户对ID一无所知 - 通过向
Entity
添加默认构造函数,简化了Entity
堆实例的创建。现在,您可以使用m_Object{ std::make_unique<Entity>() }
初始化您的Lucre::m_Object
成员
【演示】
#include <cstdint> // uint32_t
#include <iostream> // cout
#include <memory> // make_unique, unique_ptr
class Entity
{
public:
Entity(): m_ID{currentID++} {}
Entity(const Entity&) = delete;
Entity& operator=(const Entity&) = delete;
Entity(Entity&&) = default;
Entity& operator=(Entity&&) = default;
auto getID() const { return m_ID; }
friend std::ostream& operator<<(std::ostream& os, const Entity& e) { return os << e.m_ID; }
private:
static inline uint32_t currentID;
uint32_t m_ID;
};
struct Lucre
{
Lucre() : m_Object{ std::make_unique<Entity>() } {}
friend std::ostream& operator<<(std::ostream& os, const Lucre& l) { return os << l.m_Object->getID(); }
private:
std::unique_ptr<Entity> m_Object{};
};
int main()
{
Lucre lucre1{};
Lucre lucre2{};
std::cout << "lucre1 = " << lucre1 << ", lucre2 = " << lucre2 << "n";
}
// Outputs:
//
// lucre1 = 0, lucre2 = 1