2

(I come from C world and I am a beginner in C++, so simply answer the question)

In c++, argument are passed by value. So I try the following code to understand how it works.

#include <iostream>

using namespace std;

class MyClass {
    int a;
    public:
        MyClass() {
            a = 0;
            cout<<"Default Constructor call\n"; }
        MyClass(int x) {
            a = x;
            cout<<"Constructor call\n"; }
        ~MyClass() {
            cout<<"Destructor call\n"; }
};

void myfoo(MyClass arg) {}

int main() {
    cout<<"Obj declaration\n";
    MyClass obj(10);
    cout<<"Function call\n";
    myfoo(obj);
    cout<<"End of main\n";
}

The destructor is called at the end of the function and the constructor is not called at the beginning because there is no constructor MyClass(MyClass& xxx).
So, how the object arg is constructed in the function ? A simple memory copy ? Is it enough or is it better to always have a constructor MyClass(MyClass& xxx)

Stef1611
  • 1,978
  • 2
  • 11
  • 30
  • 2
    About [using namespace std](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)... – Aconcagua Aug 09 '19 at 08:15
  • 1
    *'Is it enough or is it better to always have a [copy] constructor [...]?'* As given in the answers already, if you don't provide one, it will be created implicitly (but there are some exceptions, e. g. if you explicitly provide a move constructor, or if you have non-copiable members). Sometimes, this default copy constructor is appropriate, sometimes not. In any case, keep an eye on the rules of [three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) and [five](https://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11)! – Aconcagua Aug 09 '19 at 08:45

2 Answers2

3

and the constructor is not called at the beginning

Not quite correct. The copy constructor is called, which is implicitly defined by the compiler. You can define one yourself:

MyClass(const MyClass& other) { cout << "Copy Constructor call\n"; }

The implicit copy constructor copies each member using its copy constructor. If any of the members cannot be copied, the copy constructor is implicitly deleted.

One can explicitly disable the copy constructor. In pre C++11 days, the idiom was to declare it private. In modern C++, the delete keyword is used:

MyClass(const MyClass& other) = delete;

If you do this, the code won't compile.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • Thanks for answer concerning the implicit definition. It is what I needed. (Rq : I was aware argument could be passed by reference). – Stef1611 Aug 09 '19 at 08:17
  • @Stef1611 please also note the edit; the constructor may be deleted. – Aykhan Hagverdili Aug 09 '19 at 08:20
  • 1
    @Stef1611 Note that the definition of an implicit copy constructor (and copy assignment operator) is deprecated when your class has a user defined destructor. The compiler will do it as of now (C++17), but this might be removed in a future version of C++. Your code would then not compile anymore and would behave as if you wrote `MyClass(const MyClass&) = delete;` in your class. – Nikos C. Aug 09 '19 at 08:20
  • @NikosC. Concerning the Implicitly-declared copy constructor, how does it work ? I suppose it is not a simply memory copy. Why is it deprecated ? – Stef1611 Aug 09 '19 at 08:26
  • 1
    @Stef1611 It just calls the copy constructors of any of the members... And primitive types (int, double, ...) indeed are copied. – Aconcagua Aug 09 '19 at 08:28
  • 2
    @all. I have very appreciated your simple answer. Thanks a lot. I accepted the answer. – Stef1611 Aug 09 '19 at 08:30
  • @Stef1611 As others mentioned, the implicitly defined one will just do a member-wise call to the copy constructor of each member. As to why the implicit copy ctor is deprecated, you can google for "C++ rule of five". It's a bit complicated if you're new to C++. Also look up "C++ rule of zero", which is what you should strive for to keep things as simple and as intuitive as possible. It's not always possible of course. – Nikos C. Aug 09 '19 at 08:42
  • @NikoC. Thanks for these keywords (rule of five). It is not so complicated but C programming background helps. – Stef1611 Aug 09 '19 at 08:47
3

because there is no constructor MyClass(MyClass& xxx).

This is not correct, there is a copy constructor with the signature MyClass(const MyClass&) which is generated by the compiler for you. You can provide your own implementation and write something to the standard output to see that.

MyClass(const MyClass& other) : a(other.a) {
        cout<<"Copy constructor call\n";
}

Note that the question when the compiler generates special member functions for you is a bit involved. Maybe too much at the very beginning, but at some point you will have to know. A good overview is the table in this answer.

lubgr
  • 37,368
  • 3
  • 66
  • 117
  • 2
    Or, if you want to see what happens when there really isn't a copy constructor, then you can do `MyClass(const MyClass&) = delete;`. – Nikos C. Aug 09 '19 at 08:15