带参数的复制构造函数:shared/unique_ptr 不引用相同的数据

问题描述 投票:0回答:1

////////////////////////////////代码

#include <iostream>
#include <list>
#include <memory>

using namespace std;

class B
{
  int b;

public:
  B(){};
  B(int _b)
  {
      b = _b;
  }
  int getb() const {return b;}
  void setb(int _b)  {b=_b;}
}; 

class A
{
 private:
   list<B*> myList;
   B isb;
   unique_ptr<B> smartUniq;
   shared_ptr<B> smartShared;
   

 public:
   A(): isb(10), smartUniq(make_unique<B>(20))
   {
      myList.push_back(new B(5));
      myList.push_back(new B(6));
      myList.push_back(new B(7));
      
      int x=30;
      smartShared = make_shared<B>(x);
   }
   ~A()
   {
      for (auto& item : myList)
      {
         
         delete item;
      }
      cout << "destructor"<<endl;
   }
   void displayData()
   {
       
     cout << "List Items:" << endl;  
     for (auto& item : myList)
     {
         cout << item->getb()<<endl;
     }
     cout << "isb:"<<isb.getb() << endl;
     cout << "smartUniq:"<<smartUniq->getb() << endl;
     cout << "smartShared:"<<smartShared->getb() << endl;
   }
   void Set(int currentValue, int b) 
   {
      for (auto& item : myList)
      {
         if (currentValue == item->getb())
         {
             item->setb(b);
             break;
         }
     }
     isb.setb(15);
     smartUniq->setb(25);
     smartShared->setb(80);
   }
   // Copy constructor
   A(const A &src): smartUniq(make_unique<B>(*src.smartUniq)),smartShared(make_shared<B>(*src.smartShared))
   {
     for (auto& item : src.myList)
     {
       myList.push_back(new B(item->getb()));
     }
     isb = src.isb;
  }

   // Copy assignement
   A& operator= (const A &src)
   {
  
     for (auto& item : src.myList)
     {
       if (item != nullptr)
          delete item;
     }
      
     for (auto& item : src.myList)
     {
       myList.push_back(new B(item->getb()));
     }
     isb = src.isb;
     
     smartUniq=make_unique<B>(*src.smartUniq);
     smartShared=make_shared<B>(*src.smartShared);
     
     return *this;
   }
};  
 
int main()
{

    A a1;
    
    A a2{a1};
    
    a1.Set(6,9);    
    
    std::cout<<"a1:" <<endl;
    a1.displayData();
    std::cout<<"a2:" <<endl;
    a2.displayData();
    
    return 0;
}

/////////////////////////////输出

a1:
List Items:
5
9
7
isb:15
**smartUniq:25**
smartShared:**80**

a2:
List Items:
5
6
7
isb:10
**smartUniq:20**
smartShared:**30**

destructor
destructor

///////////////////////////////////////问题

1.我不知道为什么2个智能ptr:“smartUniq”和“smartShared”在更新a1和a2对象的值后不引用相同的数据(它们通常是指针:

  • a1.smartUniq 值 =a2.smartUniq 值
  • (与 smartShared 相同))
  • --> 当我删除复制构造函数时:它们正确引用相同的值(a1.smartUniq 值 =a2.smartUniq 值)
  1. 在复制分配中,如果动态成员类已经实例化,有什么实用程序可以删除它们?
     for (auto& item : src.myList)
     {
       if (item != nullptr)
          delete item;
     }
c++
1个回答
0
投票

“唯一”指针就是这样,它们每个都拥有唯一且单一的数据所有权。使用唯一的指针,您实际上无法拥有任何类型的共享或混合所有权。这实际上是您应该如何看待这些智能指针:作为某些资源的所有权,该资源可以是单一所有者(唯一)、共享所有者(共享),或者根本没有所有权语义(普通非智能指针)。

实际上,在

A
复制构造函数中
smartUniq(make_unique<B>(*src.smartUniq))
将创建一个全新的
B
对象,该对象与
src.smartUniq
所指向的对象完全无关。从那一刻起,您将有两个不同的指针指向两个不同的对象。与
smartShared
类似,您可以创建一个全新的副本。

© www.soinside.com 2019 - 2024. All rights reserved.