Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly initialize class value member?

Tags:

c++

lets say we have this:

class Foo {

    public:
    Foo(const Bar& b) : m_bar(b) {}

    private:
    Bar m_bar;
};

Now regarding efficiency C++ FAQ LITE says this:

Consider the following constructor that initializes member object "x" using an initialization list: Fred::Fred() : x(whatever) { }. The most common benefit of doing this is improved performance. For example, if the expression whatever is the same type as member variable "x", the result of the whatever expression is constructed directly inside "x" — the compiler does not make a separate copy of the object.

Should the constructor better have the parameter as value instead of reference?

Since I am using the constructor initialization list, would there be a performance difference?

Finally, and most important, would there be a semantic difference? e.g., to the caller of new Foo(Bar())

Thank you

-- Edit -- Corrected the parameter declaration as const reference.

like image 249
Dimitrios Menounos Avatar asked Dec 08 '25 10:12

Dimitrios Menounos


2 Answers

For the purposes of what your quote is talking about, "if the expression whatever is the same type as member variable x_" is true even if b is a Bar reference and m_bar is a Bar object.

Taking the parameter by value could be slower, since if anything it's likely to result in an extra copy.

As Josef and SoapBox say, the reference should be const. Otherwise you can't pass temporaries. It's legal to have a constructor which modifies its argument, but it's very rarely a good idea, at least until C++0x move semantics arrive.

like image 72
Steve Jessop Avatar answered Dec 10 '25 00:12

Steve Jessop


I'll break it down into performance and semantic differences, as you requested:

Should the constructor better have the parameter as value instead of reference?

Unless it is a primitive type or small struct, it should have the parameter passed by const reference. Passing by reference gives you a performance difference: the program does not have to make a copy of the whole object before passing it to the constructor. For small objects, however, the time saved by avoiding the copy may not be offset by the extra level of indirection.

Passing by const ensures that you can call the constructor with temporary objects. Thus, to the caller of the constructor, there is no semantic difference as to whether you are calling by value or by const reference.

Since I am using the constructor initialization list, would there be a performance difference?

If you do not use the initialization list, and the object you are initializing has a default constructor, this is what happens semantically:

class Foo
{
    Bar bar;
    Foo(const &Bar bar_)
    /* bar(Bar()) is implicitly called here,
    before the start of the function body */
    {
        /* Note that we cannot do bar(bar_) now
        as bar has already been constructed.
        So we might do this instead: */
        bar = bar_; // the assignment operator function is called here
    }
};

However, if the compiler is able to see that the default constructor of Bar has no side effects other than to initialize bar, and that this value of bar is overwritten in the body of the constructor, it may choose to elide (remove) this call completely. But we can always make life easier for the compiler and not make that extra call.

Note that if the object you want to initialize does not have a default constructor, then you must initialize it in the initialization list. This is another semantic difference.

like image 23
int3 Avatar answered Dec 10 '25 01:12

int3



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!