0

I recently started learning C++ and I can't understand the following code (it's a copy constructor, deep copy):

Car::Car(const Car &c){
this->_make = new string(*(c._make));
this->_model = new string(*(c._model));
this->_year = new int(*(c._year));
}

Here, we are passing by reference so why are we adding the "*" here: *(c._make), shouldn't it just be c._make, as passing by reference already gives the value, what does the * do in this case?

jas305
  • 79
  • 6
  • 6
    This looks like someone's terrible port of C++ from Python or something. Way too much use of pointers where none are needed. – Nicol Bolas Oct 21 '20 at 04:01
  • So how would I make this simpler? – jas305 Oct 21 '20 at 04:04
  • 1
    @jas305 - yes, you're correct. And if you're trying to learn C++ from examples like this ... it's time to find some new examples. Fast! – paulsm4 Oct 21 '20 at 04:05
  • 1
    Every time you use `new` you're responsible for one of the most deceptively hard problems in all programming: cleaning up the mess. Handy reading: [Why should C++ programmers minimize use of 'new'?](https://stackoverflow.com/questions/6500313/why-should-c-programmers-minimize-use-of-new) – user4581301 Oct 21 '20 at 04:10
  • 1
    "So how would I make this simpler?" Never use raw pointers that own memory. Follow the [rule of zero](https://en.cppreference.com/w/cpp/language/rule_of_three) and don't write copy contructors. – bolov Oct 21 '20 at 04:27

3 Answers3

1

You need * in this->_make = new string(*(c._make)); because make was defined as a pointer:

class Car
{
   string* make;
   //...
};

This design is pointless - it would be better to hold string by value:

class Car
{
   string make;
   //...
};

In which case the code in question would look like:

    Car::Car(const Car &c){
    this->_make = c._make;
//...
}

with no * anywhere.

Eugene
  • 4,579
  • 1
  • 16
  • 29
  • 2
    Even better: If all of the members are `std::string` you can safely observe [the Rule of Zero](https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_zero) and have no copy constructor at all. The compiler will generate the correct copy constructor for you because `std::string` observes the [Rule of Five](https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_five) and copies itself. – user4581301 Oct 21 '20 at 04:18
1

The * is not being applied to the passed Car object itself, but to its 3 pointer members, _make, _model, and _year. The pointers are being dereferenced when the members are being passed to their respective copy constructors.

Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
1

It's hard to see why a deep copy is necessary for 3 simple variables. Nevertheless if they were defined as pointers in the class then they need to be dereferenced otherwise you would be copying the address of the values instead of the values themselves. The fact that the object is being passed by reference doesn't mean that its member variables are being referenced as well.

Deep copying is useful when the class includes dynamically allocated arrays, or other classes, etc. But for simpler classes with simple variables (no pointers), a shallow copy should be enough.

Ric
  • 121
  • 3