【问题标题】:assignment operator error in unique pointer唯一指针中的赋值运算符错误
【发布时间】:2019-01-27 07:15:04
【问题描述】:

我尝试在 C++ 中以单例模式使用unique_ptr,而不是原始指针。当我想将unique_ptr 分配给另一个时,我得到了一个错误。我尝试使用std::move 进行分配,但没有成功。代码如下:

#include <iostream>
#include <memory>
#include <list>
#include <algorithm>
#include <iterator>
#include <string>

using namespace std;

class ClientDB
{
  private:
    static unique_ptr<ClientDB> theDB;
    ClientDB() {}
    list<string> clients;
  public:
    ~ClientDB() {}
    static unique_ptr<ClientDB> getInstance()
    {
      if(theDB==nullptr)
    theDB = make_unique<ClientDB>;
      return theDB;
    }
    void addClient(string c) {clients.push_back(c);}
    void printClients(ostream& os)
    {
      copy(clients.cbegin(),clients.cend(),ostream_iterator<string>{os,"\n"});
    }
};


int main()
{
  unique_ptr<ClientDB> db1{ClientDB::getInstance()};
  db1->addClient("Mr. Schultz");
  unique_ptr<ClientDB> db2{ClientDB::getInstance()};
  db2->addClient("Mrs. James");
  unique_ptr<ClientDB> db3{ClientDB::getInstance()};
  db3->addClient("Mr. Karajan");
  db1->printClients(cout);
}

我得到的错误是

error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<ClientDB>’ and ‘<unresolved overloaded function type>’)
     theDB = make_unique<ClientDB>;

另一个问题是nullptr 是否可以用于unique_ptr

【问题讨论】:

  • make_unique&lt;ClientDB&gt; 需要被调用make_unique&lt;ClientDB&gt;()。请注意,您的方法仍然无效。在保留对象所有权的同时,您不能返回 unique_ptr。
  • @StoryTeller 你是对的。这是我收到的另一个错误 `error: use of deleted function 'std::unique_ptr<_tp _dp>::unique_ptr(const std::unique_ptr<_tp _dp>&) [with _Tp = ClientDB; _Dp = std::default_delete]' return theDB;'
  • 是的,这就是复制构造函数(它不存在,因为 unique_ptr 想要......嗯,独一无二)。
  • 基本上,return theDB 正在尝试创建 unique_ptr 的副本,这是被禁止的。您可以返回引用unique_ptr&amp;unique_ptr 管理的原始指针:return theDB.get()
  • 不要使用 Singleton,如果你这样做,不要使用 unique_ptr。见stackoverflow.com/a/1008289/2466431

标签: c++ unique-ptr


【解决方案1】:

终于在老师的帮助下,我解决了这个问题。有几点需要考虑。

1- 对于unique_ptr 分配,应使用std::move::

2- make_unique 无法访问私有构造函数,应显式调用构造函数: theDB = unique_ptr&lt;ClientDB&gt;(new ClientDB());

3-unique-ptr 必须在类外初始化: unique_ptr&lt;ClientDB&gt; ClientDB::theDB;

4- 同一对象的 main 中不能使用三个唯一指针,唯一性只允许使用一个。应该使用对unique_ptr 的引用: unique_ptr&lt;ClientDB&gt;&amp; db1=ClientDB::getInstance();

最后代码应该是这样的

#include <iostream>
#include <memory>
#include <list>
#include <algorithm>
#include <iterator>
#include <string>

using namespace std;

class ClientDB
{
private:
  static unique_ptr<ClientDB> theDB;
  ClientDB() {}
  list<string> clients;
public:
  ~ClientDB() {}
  static unique_ptr<ClientDB>& getInstance()
  {
    if(theDB==nullptr)
      //theDB = move(make_unique<ClientDB>());
      theDB = unique_ptr<ClientDB>(new ClientDB());
    return theDB;
  }
  void addClient(string c) {clients.push_back(c);}
  void printClients(ostream& os)
  {
    copy(clients.cbegin(),clients.cend(),ostream_iterator<string>{os,"\n"});
  }
};
unique_ptr<ClientDB> ClientDB::theDB;

int main()
{
  unique_ptr<ClientDB>& db1=ClientDB::getInstance();
  db1->addClient("Mr. Schultz");


  unique_ptr<ClientDB>& db2=ClientDB::getInstance();
  db2->addClient("Mrs. James");


  unique_ptr<ClientDB>& db3=ClientDB::getInstance();
  db3->addClient("Mr. Karajan");

  db1->printClients(cout);
}

【讨论】:

  • unique_ptr 的引用通常是没有意义的。 getInstance 应该返回原始指针 ClientDB* 或引用 ClientDB&amp;,因为调用者根本不参与管理对象的生命周期。除非您希望代码能够通过unique_ptr&lt;ClientDB&gt; mine = std::move(ClientDB::getInstance()); 窃取对象并使其不是真正的单例!
猜你喜欢
  • 1970-01-01
  • 2021-05-13
  • 1970-01-01
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
相关资源
最近更新 更多