1

I'm creating a program which has an abstract base class called component, I have 3 classes inductor, resistor and capacitor which inherit from components. I have a vector:

std::vector<component*> components;

Which is a member of a class called circuit. So components contains pointers to component objects (whether that be resistor, capacitor or inductor).

Now my problem arises when I try and create a new vector, initialized as so:

std::vector<component*> temp_components = components;

Currently the vector only contains resistor objects, so I have a copy constructor in 'resistor.cpp':

resistor::resistor(const resistor& resistor)
{
    impedance = resistor.impedance;
    voltage_frequency = resistor.voltage_frequency;
    name = resistor.name;
    resistance = resistor.resistance;
}

And also an assignment operator in resistor:

resistor& resistor::operator=(resistor& rhs)
{
    //Check if equal
    if (&rhs == this) {
        return *this;
    }

    delete& impedance; delete& voltage_frequency; delete& name; delete& resistance;
    impedance = rhs.impedance;
    voltage_frequency = rhs.voltage_frequency;
    name = rhs.name;
    resistance = rhs.resistance;

    return *this;
}

However, when I run the code to create temp_components equal to components, the pointers in the 2 vectors are the same, so when I change a value in temp_components, it does the same in components, which is not what I want.

I think this is because of the way vector works for pointers, but I have no idea where to begin in fixing this problem. I want to make it so the details (class members) of the components which the pointers point to are copied, but the pointers don't both point to the same memory location.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
ryani42
  • 111
  • 2
  • *"the memory addresses of the 2 vectors are the same"*. This cannot happen in C++. Every object has different address than any other object in the program. – Jason May 18 '22 at 14:19
  • 6
    @AnoopRana I suspect he means that the memory addresses _contained in the vectors_ are the same. Which is to be expected because making a copy of a `std::vector` will create a separate vector that contains the same _pointers_ as the original vector, not pointers to copies of those elements. – Nathan Pierson May 18 '22 at 14:20
  • 3
    `std::vector temp_components = components;` ... This is a vector of pointers. The pointers are copied. They objects they point to will not be. – ChrisMM May 18 '22 at 14:20
  • 1
    @AnoopRana Sorry that was vague of me. When I output say the 1st item of components and 1st item of temp_components, the pointer has the exact same value. I have edited to clarify – ryani42 May 18 '22 at 14:21
  • 1
    *I think this is because of the way vector works for pointers,* -- A vector does not do anything different for pointers as for any other object. A pointer is simply a value, and the same value-semantics that vector has for other objects, it has for pointers. – PaulMcKenzie May 18 '22 at 14:22
  • https://stackoverflow.com/questions/5148706/copying-a-polymorphic-object-in-c might help. – Thomas May 18 '22 at 14:22
  • @ryani42 -- If your goal is to have the pointers shared, then `std::vector>` is what you may want to use instead of what you have now. – PaulMcKenzie May 18 '22 at 14:26
  • @NathanPierson Yes, the pointers are copied and not the underlying objects to which those pointers point, which i think is no surprise in this case. – Jason May 18 '22 at 14:26
  • 2
    @PaulMcKenzie It sounds like the intention is that the new vector should actually have different pointed-to objects. Sounds like a `component::clone()` method is called for – Nathan Pierson May 18 '22 at 14:30
  • If by "memory addresses of the two vectors are the same" you mean "copying the vector of pointers creates a second vector containing the same pointers" rather than "the pointers in the second vector point at clones of objects pointed to by elements of the first vector" then that is EXACTLY what is required to happen. If you want something different, you need to write explicit code to do it (e.g. write a loop of the form (C++11 and later) `std::vector temp_components; for (component *element : components) {temp_components.push_back(new component(*element));}`). – Peter May 18 '22 at 14:31
  • 1
    The search term you are looking for is _shallow copy_ vs _deep copy_. – CompuChip May 18 '22 at 14:34
  • 1
    If you copy a vector of ints, you get two vectors with the same ints. If you copy a vector of pointers, you get two vectors with the same pointers. This should not be a surprise. – user253751 May 18 '22 at 14:49
  • Why does your copy constructor not use an initializer list? – Chris May 18 '22 at 15:21
  • 1
    @Chris: The copy constructor in the question is just doing what the compiler-generated one would do, only without exception safety (which a ctor-initializer-list could help with) and with increased maintenance burden (which the ctor-initializer-list helps not at all). It should just be removed. The assignment operator is horribly broken (separately deleting member subobjects) and also needs to be removed, as the compiler-generated one will do fine. – Ben Voigt May 18 '22 at 15:32
  • @BenVoigt Hahaha christ, okay thank you ill get rid of them and go about creating some better ones. – ryani42 May 18 '22 at 16:03
  • How about using `union AnyComponent { Component base; Inductor i; Resistor r; Capacitor c; }; std::vector v;`? `std::any` or `std::variant` are also possible. – Goswin von Brederlow May 18 '22 at 16:21

0 Answers0