无法从类成员函数返回 unique_ptr

时间:2021-01-28 07:19:52

标签: c++ design-patterns smart-pointers

在实现构建器设计模式时,我无法从类成员函数返回 unique_ptr。作为构建器设计模式的一部分,我想使用构建器创建一个对象并将智能指针的所有权转移到客户端代码。但是,正如我从编译错误中了解到的,我发现从类成员函数中返回 unique_ptr 存在一些问题。

// Progarm to demonstrate builder design pattern.
#include <iostream>
#include <memory>

class person 
{
    std::string name_ {};
    uint8_t age_ = 0;
    std::string uniqueId_ {};

    person(std::string name):name_(name) {

    }
public:
    // Person Builder
    class personBuilder;

    // Public member function to print his info.
    void displayPersonInfo()
    {
        std::cerr << "\nName:" << name_
                    << "\nAge:" << std::to_string(age_)
                    << "\nUniqueId:" << uniqueId_
                    << "\n";
    }

    // Destructor
    virtual ~person()
    {
        std::cerr << "\nDestroy Person Object\n";
    }
};

class person::personBuilder
{
    std::unique_ptr<person> pThePerson;

public:
    personBuilder(std::string name)
    {
        pThePerson = std::make_unique<person>(name);
    }

    personBuilder & age(const uint8_t age)
    {
        pThePerson->age_ = age;
        return *this;
    }

    personBuilder & uniqueId(const std::string uniqueId)
    {
        pThePerson->uniqueId_ = uniqueId;
        return *this;
    }

    std::unique_ptr<person> build()
    {
        return pThePerson;
    }
};

int main(int argc, char** argv)
{
    std::unique_ptr<person> myPerson = person::personBuilder("Sachin Tendulkar")
                    .age(40).uniqueId("AABBCC").build();

    myPerson->displayPersonInfo();

    return 0;
}

以下是我得到的编译错误。

$ g++ 04_builder_02_short.cpp
04_builder_02_short.cpp: In member function ‘std::unique_ptr<person> person::personBuilder::build()’:
04_builder_02_short.cpp:58:16: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = person; _Dp = std::default_delete<person>]’
         return pThePerson;
                ^~~~~~~~~~
In file included from /usr/include/c++/8/memory:80,
                 from 04_builder_02_short.cpp:3:
/usr/include/c++/8/bits/unique_ptr.h:397:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^~~~~~~~~~
/usr/include/c++/8/bits/unique_ptr.h: In instantiation of ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = person; _Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<person>]’:
04_builder_02_short.cpp:41:51:   required from here
/usr/include/c++/8/bits/unique_ptr.h:835:30: error: ‘person::person(std::__cxx11::string)’ is private within this context
     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
04_builder_02_short.cpp:11:5: note: declared private here
     person(std::string name):name_(name) {
     ^~~~~~
$

2 个答案:

答案 0 :(得分:1)

您不能复制唯一指针。考虑到副本对指向的对象具有唯一所有权,并且副本的源已经拥有该对象,副本将指向什么?

目前还不清楚为什么首先涉及动态分配。也许最好将对象直接存储为成员,以便您可以复制它:

class person::personBuilder
{
    person pThePerson;

答案 1 :(得分:1)

unique_ptr 是唯一的所有权对象,这意味着它的复制构造函数和赋值运算符被删除。所以你不能复制。可以移动唯一所有权对象。您可以通过`

返回unique_ptr
return std::move(unique_ptr);
相关问题