Code
#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;
}
Output
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
Questions
-
I don’t know why the 2 smart ptr: "smartUniq" and "smartShared" dont refer to the same data after the update value for a1 and a2 object (they are pointers, normally :
- a1.smartUniq value =a2.smartUniq value
- (same for smartShared))
- –> when i delete copy constructor : they refer correctly to the same value (a1.smartUniq value =a2.smartUniq value)
-
In the copy assignement, what is the utility to delete dynamic member class if they are already instanciated?
for (auto& item : src.myList)
{
if (item != nullptr)
delete item;
}
>Solution :
"Unique" pointers are just that, they each have a unique and single ownership of data. With a unique pointer you can’t really any kind of shared or mixed ownership. Which is really how you should look at those smart pointer: As ownership of some resource, which is either single owner (unique), shared owners (shared), or no ownership semantics at all (plain non-smart pointers).
Actually, in the A copy-constructor smartUniq(make_unique<B>(*src.smartUniq)) will create a brand new B object, one that is totally unrelated to the one that src.smartUniq is pointing to. From that moment you will have two different pointers to two different objects. Similarly with smartShared, you create a brand new copy which is unrelated to the first.
For the shared pointer you could simply use smartShared(src.smartShared) to get a pointer to the same object, which now will have shared ownership.
That’s not possible to do with smartUnique though. You either need to make a copy, or transfer the ownership completely from one object to the other.
As for your second question, which really should be a separate question with its own minimal example, it’s a bug. Instead of deleting the elements of src list you should delete the elements of the objects own list.
I’m sure you would have figured it out eventually, especially with a little rubber duck debugging.