0

I would like to understand when a copy constructor or assignment is called. Assume the following:

class Foo {
public:
   Foo()
   {
      cout << "foo constructor " << this << endl;
      test_ = 44;
   }

   Foo(const Foo& f)
   {
      cout << "foo copy constructor " << this << endl;
      test_ = 55;
   }

   Foo& operator=(const Foo& other)
   {
      cout << "foo copy assignment " << this << endl;
      return *this;
   }

   Foo& operator=(Foo& other)
   {
      cout << "foo copy non-const assignment " << this << endl;
      return *this;
   }

   ~Foo() { cout << "foo destructor  " << this << endl; };

   int bar() const {
      cout << "bar call  " << this << endl;
      return 6;
   }

   int test_;
};


class Model {
public:
   Model()
   {
      foo_ = std::make_unique<Foo>();
   }

   Foo get_foo()
   {
      return *foo_;
   }

   std::unique_ptr<Foo> foo_;
};


int main() {
   cout << "start test 1" << endl;
   {
      Model model;
      Foo foo1 = model.get_foo();
      foo1.bar();
   }
   cout << "end test 1" << endl << endl;


   cout << "start test 2" << endl;
   {
      Model model;
      const Foo& foo2 = model.get_foo();
      foo2.bar();
   }
   cout << "end test 2" << endl;


   cout << "start test 3" << endl;
   {
      Model model;
      model.get_foo().bar();
   }
   cout << "end test 3" << endl;
   return 0;
}

The output is provided at the end.

  1. Why no copy assignment is called in test 1 and a copy constructor is called?
  2. Why a copy constructor is called in test 2 and 3?
  3. what are the exact steps hapenning in test 3 regarding get_foo().bar()?

I would appreciate any type of information/problem you might have noticed in the code (e.g. the fact that get_foo() dereferences a unique pointer).

start test 1
foo constructor 000001D4EF9B6720
foo copy constructor 00000058BED6FA94
bar call  00000058BED6FA94
foo destructor  00000058BED6FA94
foo destructor  000001D4EF9B6720
end test 1

start test 2
foo constructor 000001D4EF9B6F60
foo copy constructor 00000058BED6FAF4
bar call  00000058BED6FAF4
foo destructor  00000058BED6FAF4
foo destructor  000001D4EF9B6F60
end test 2

start test 3
foo constructor 000001D4EF9B6F60
foo copy constructor 00000058BED6FBF4
bar call  00000058BED6FBF4
foo destructor  00000058BED6FBF4
foo destructor  000001D4EF9B6F60
end test 3
Sam
  • 1
  • 1
  • `=` is used for initialization and assignment. `Foo f = ...` is not assignment. The easy way to remember is: You first need an object before you can assign to it – 463035818_is_not_an_ai Aug 03 '23 at 12:33
  • 2
    please try to focus on one single question per question. All of your question already have answers somewhere, but it is seperate questions with seperate answers. SOmetimes you better split it up and write 2 or 3 seperate questions rather than squeezing it all in one. When they are closesly realted you can refer to them by adding links – 463035818_is_not_an_ai Aug 03 '23 at 12:35
  • @OP -- *I would like to understand when a copy constructor or assignment is called* -- IMO, if your class has correct copy semantics, you shouldn't concern yourself with when or where this will be done. The compiler, with optimizations turned on and with mandatory elision rules, will not call the functions you are expecting to be called. If your code has performance issues, then it would be time to see when or where copies are being made. Trying to keep up with what the compiler will do when it comes to copies -- that's exhausting (and you still may not get it right). – PaulMcKenzie Aug 03 '23 at 12:49
  • `get_foo` returns a **copy** (via copy constructor) of Foo. – Eljay Aug 03 '23 at 12:58

0 Answers0