-2

I have a class with multiple pointers as data members in it

Class A
{
    int* a;
    int* b;
    int c;
}
std::shared_ptr<A> Aa = std::make_shared<A>();
std::shared_ptr<A> Ab = std::make_shared<A>();
Ab = Aa;

Consider all the "Aa" data members (along with pointers) are initialized with some data Can I do the above shared ptr assignment directly? or Do I need to overload the assignment operator? Please help..

2 Answers2

1

std::shared_ptr is just a smart pointer, it doesn't care about the members of the object it is holding, only the object itself.

Assigning Aa to Bb will destroy the A object that Bb is holding, and then share ownership of the A object that Aa is holding.

Overloading operator= has nothing to do with whether std::shared_ptr is being used or not. Regardless of how an A object is created, or how its lifetime is being managed, A is responsible for managing its own members, by following the Rule of 3/5/0, which basically states that

if a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.

...

Because the presence of a user-defined destructor, copy-constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator, any class for which move semantics are desirable, has to declare all five special member functions

If A's members refer to outside data/resources that A is responsible for deallocating/releasing, then A needs to have proper constructors, destructor, and assignment operators implemented to manage those members properly.

As shown, your A class is likely violating the Rule of 3/5/0, but it is difficult to say for sure as you did not show how the members are being initialized with data.

For example, this would be a violation, since A does not have a destructor to free the new'ed ints that it owns:

class A
{
public:
    int* a;
    int* b;
    int c;
};

class B : public A
{
};

std::shared_ptr<A> Aa = std::make_shared<A>();
a->a = new int(123);
a->b = new int(456);
a->c = 7890;

std::shared_ptr<A> Bb = std::make_shared<B>();
Bb = Aa;

Whereas this would not be a violation, since A does not own the ints that it is pointed at:

class A
{
public:
    int* a;
    int* b;
    int c;
};

class B : public A
{
};

int a = 123;
int b = 456;

std::shared_ptr<A> Aa = std::make_shared<A>();
a->a = &a;
a->b = &b;
a->c = 7890;

std::shared_ptr<A> Bb = std::make_shared<B>();
Bb = Aa;

Assuming A is responsible for owning the allocated memory for the ints , a conforming Rule Of 3/5/0 implementation might look more like this:

class A
{
public:
    std::unique_ptr<int> a;
    std::unique_ptr<int> b;
    int c = 0;

    A() = default;

    A(const A &src) :
        a(std::make_unique<int>(*src.a)),
        b(std::make_unique<int>(*src.b)),
        c(src.c)
    {
    }

    A(A &&src) :
        a(std::move(src.a)),
        b(std::move(src.b)),
        c(src.c)
    {
        src.c = 0;
    }

    virtual ~A() = default;

    A& operator=(A rhs)
    {
        std::swap(a, rhs.a);
        std::swap(b, rhs.b);
        std::swap(c, rhs.c);
        return *this;
    }
};

class B : public A
{
};

std::shared_ptr<A> Aa = std::make_shared<A>();
a->a = std::make_unique<int>(123);
a->b = std::make_unique<int>(456);
a->c = 7890;

std::shared_ptr<A> Bb = std::make_shared<B>();
Bb = Aa;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Assigning one shared pointer to another in the way you've shown does not involve calling a copy constructor on your class A, and so does not require it being defined.

std::shared_ptr<A> Aa = std::make_shared<A>();
std::shared_ptr<A> Bb = std::make_shared<B>();
Bb = Aa; // Copy assignment for shared_ptr (you now have two pointers to the same data)

To call the copy constructor of A, you would have to write:

std::shared_ptr<A> Aa = std::make_shared<A>();
std::shared_ptr<A> Bb = std::make_shared<B>();
*Bb = *Aa;

But then you should consider if you're creating problems with object slicing: What is object slicing?

Chris Pearce
  • 666
  • 5
  • 16
  • Sorry for the confusion created, there is only one class A here. Both the shared pointers (Aa and Ab) are of the same class type. I have edited the code accordingly. – user3060163 Sep 04 '20 at 04:57