简体   繁体   中英

C++ Always Const Reference in Constructor?

So consider following code:

#include <iostream>
using namespace std;

class A {
public:
    A() = default;

    A(const A& rhs) {
        cout << "Copy was made!" << endl;
    }
};

class B {
public:
    A data;
    int foo;

    B(A data, int foo) : data(data), foo(foo) {
    }
};

int main() {
    A data;

    B foo(data, 10);

    return 0;
}

This prints out:

Copy was made!

Copy was made!

Yes thats right, it copies twice!

The first copy happends when we pass data to B's constructor. The second copy happends when we copy data from the constructor to the memeber variable.

We know that we can not go under 1 copy (unless we go heap & pointers ). So why don't we always write:

B (const A& data, const int& foo, const SomeOtherType& bar, const float& aFloatyNumber) ... and so on.

I know that it's cheap to pass int, float etc by value. But by always having const ref as Constructor parameters we will guarantee 1 fewer copies.

If you do not move objects you are consuming you actually should pass your arguments by references, probably as a T const& . If you do consume your argument, you should pass objects of move-aware types (ie, types defining a move-constructor) by value and move it. That is, if A is move-aware, ie, has a constructor A::A(A&&) , you'd use:

B(A data, int foo) : data(std::move(data)), foo(foo) {
}

If your types are not move-aware or you don't need to squeez the last bit of performance out of the construction or the types are move-only, you can safely pass objects by T const& .

Your query has contradiction.

In first case when you pass by value you are making other object using first one that is why constructor is needed to be called again.

Secondly, passing objects as reference and primitives by values is done for size optimization.

If you want to pass int as const ref or pointer that is okay you can do it but are you getting anything out of it.

If you want to copy that value in called function in some other variable then again constructor will be called.

So if you want to store values in called function's local variables, constructor has to be called again irrespective of whether it was passed by value or reference.

Primitive types are not copied around when they needn't. They stay on the stack or in a register until the end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM