【问题标题】:Not able to return a unique_ptr from a class member function无法从类成员函数返回 unique_ptr
【发布时间】:2021-01-28 07:19:52
【问题描述】:

在实现构建器设计模式时,我无法从类成员函数返回 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) {
     ^~~~~~
$

【问题讨论】:

  • 如果它实际上不是唯一的,则不能返回唯一指针。 pThePerson 是您班级的成员。通过退回它,您可以与他人分享它。

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


【解决方案1】:

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

return std::move(unique_ptr);

【讨论】:

    【解决方案2】:

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

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

    class person::personBuilder
    {
        person pThePerson;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 2011-05-18
      • 2018-05-22
      相关资源
      最近更新 更多