Bastien Pasdeloup
Bastien Pasdeloup

Reputation: 1129

Automatic determination of the constructor initialization list by the compiler?

I was asking myself (and couldn't find an answer) if the modern C++ compilers could check into the body of the constructors to see if they could infer the initialization list, instead of letting the developer specifying it?

As an example, consider the following code:

MyClass::MyClass (Obj o)
{
    _o = o;
}

Can the compiler automatically translate it into:

MyClass::MyClass (Obj o) : _o(o)
{}

Thanks

Upvotes: 0

Views: 72

Answers (3)

This is not possible as it completely changes the semantics of the program in the general case. Some of the examples:

// Order of evaluation:
struct Foo {
   int a, b;
   Foo() : b(a) { a = 1; }    // differs from Foo() : a(1), b(a) {}
};

// Legality of the operation:
struct X { explicit X(int x); };
struct Foo {
    X x;
    Foo() { x = 5; }              // Ill formed, while Foo() : x(5) is well formed
};

// Different effects even if allowed
struct X {
   X(int)            { std::cout << "int\n";        }
   X()               { std::cout << "default\n";    }
   X& operator=(int) { std::cout << "assignment\n"; }
};
struct Foo {
   X x;
   Foo() { x = 5; }          // prints: default\nassignment\n
   // Where Foo() : x(5) {}  // prints: int\n
};

At the language level both operations are completely different and cannot be transformed. That being said, the optimizer might be able to produce the exact same code for both if they are truly equivalent.

Upvotes: 1

Brian Bi
Brian Bi

Reputation: 119219

No, because the semantics are different. The following direct-initializes the member _o from o:

MyClass::MyClass (Obj o) : _o(o)
{}

On the other hand, the following default-initializes _o and then assigns the value of o to it:

MyClass::MyClass (Obj o)
{
    _o = o;
}

In some cases there really might be no effective difference, such as if Obj is actually int. In cases where there is no effective difference, perhaps the compiler will generate the same code for both cases, but then again, maybe not. Depends how clever the optimizer is.

Upvotes: 1

BЈовић
BЈовић

Reputation: 64223

They are checking (if member variables needs to be created with parameters).

For example, this :

struct A {
  A( int ) {}
};

struct B {
  B(){ a = A(3); }

  A a;
};

is going to fail with an error.

On the other hand, some types do not need parameters to be initialized. For example :

struct A
{
    A(){
        v = 3;
    }

    int v;
};

The standard doesn't require the compiler to issue a warning, but some compilers are capable of doing it (gcc has -Weffc++ flag).

Also, there are static code analysis tools to warn about such "errors".

Upvotes: 0

Related Questions