2
votes

I am writing code that that requires me to keep a collection of two types of objects (e.g. class Derived1 and class Derived2)that have the same base class (e.g. class Base) . The base class also has a pure virtual function that has an implementation in both of these derived classes.

I keep track of all these objects using a vector of points to objects of the base class (i.e. vector<*Base> myCollection). However, I often need to make copies of this vector.

I tried to create a copy function in the base class so that I may create other instances of either Derived1 or Derived2. However, I noticed some weird behavior.

Here is an example of this behavior:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class A
{
public:
    int member;
    string name;
    A(int x, string str = "Base"): member(x), name(str) {}
    A* CreateCopy()
    {
        A tmp = A(member);  // tmp: member = 77, name = "Base"
        return &tmp;        // &tmp: member = 77, name = ""
    }
};

class B : public A
{
public:
    B(int x) : A(x, "Derived Class") {}
};

int main()
{
    A* ptr = &B(77);                // &tmp: member = 77, name = ""
    B test(77);                     // test: member = 77, name = "Derived Class"
    A* ptr2 = &test;                // *ptr2: member = 77, name = "Derived Class"
    A* newPtr = ptr->CreateCopy();  // *newPtr: member = 77, name = ""

    return 0;
}

When I create an object B and assign the reference of the object on the same line, I lose the correctness of the name member. However, when I create the object, and then assign it's reference, it works. Unfortunately I get the same issue with my CreateCopy() method.

What is happening here and what is the best way to copy a vector of pointers? Is it possible to perform the copy without using the "new" operator? It seems like memory leaks are more likely to happen while using this operator.

Thank you so much for your advice!

1
You can't return the address of a temporary like that (it's undefined behavior). I suggest you turn up your compiler's warning level and pay attention to those warnings. If you want to work with pointers like that, you'll need to allocate memory with something like new.Cornstalks

1 Answers

2
votes

For A* ptr = &B(77);, B(77) is a temporary object which will be destroyed when the expression finished, and then ptr will become a dangled pointer.

For

A* CreateCopy()
{
    A tmp = A(member);  // tmp: member = 77, name = "Base"
    return &tmp;        // &tmp: member = 77, name = ""
}

tmp is a local variable which will be destroyed when out of the scope of the function, that means CreateCopy() will return a dangled pointer.

Is it possible to perform the copy without using the "new" operator? It seems like memory leaks are more likely to happen while using this operator.

You could use smart pointer to avoid manual memory management. Such as std::unique_ptr or std::shared_ptr.