4

Can someone explain why I cannot initialise a variable in the body of the constructor in the same way as I can do it in the member initialisation list.

class MyClass
{
  public:
    MyClass();
    virtual ~MyClass(void);
  private:
    std::string test;
};

MyClass::MyClass()
: test("asdf")  <-- Case 1: This is OK
{
    test("asdf");   <-- Case 2: This is not
}

I'm asking as I have a 3rd party class that I need to use and initialize by passing certain variables into its constructor. It is fine if I use it as in Case 1 above but not as in Case 2.

1
  • 3
    You can't call test as a function. Commented Jul 22, 2016 at 13:46

5 Answers 5

10

The syntax varies between constructing an object in the member initialisation list and assigning it a value in the body of the constructor.

In the initialisation list, it is as you have it;

MyClass::MyClass()
:test("abcd")
{
  //...
}

In the body, you can use the assignment syntax

test = "abcd"; 

The syntax test("asdf"); is parsed as a function called test that is being called with a argument of "abcd".

It must be borne in mind that if the member does not have a default constructor, the initialisation list is the only place to correctly construct the member. Once the body of the constructor runs, all the member have been constructed or initialised in some manner. They may be assigned to, if possible (e.g. not applicable to references and const members etc.), but not reconstructed.

Sign up to request clarification or add additional context in comments.

2 Comments

Another nice property of the initialization list is that it allows to initialize const members that by definition you cannot change.
I would say "they may be assigned to" because some of them cannot be assigned, only initialized, for example reference.
6

You cannot initialize a variable in the constructor's body, because the constructor's body runs after all base classes and members have already been initialized in the member initialization list. That they are implicitly default-initialized because you didn't list them there is irrelevant.

So, in the body, test("asdf"); tries to call operator() on test, which fails. Use assignment (test = "asdf";) to change its value, or better yet initialize it directly in the member initialization list.

Comments

1

You have bellow ways to initialize variables in constructors :

class MyClass
{
public:
    MyClass();
    virtual ~MyClass(void);
private:
    std::string test;
};

way 1 :

MyClass::MyClass() : test("asdf")
{
}

way 2 :

MyClass::MyClass()
{
    test = "asdf";
}

7 Comments

Technically that is not initializing since the string gets default constructed by the constructor before entering the ctor body. It is assignment inside the ctor body.
@NathanOliver yes, string is a class and initialize in it-self constructor.
test = "asdf"; is not initialization. When the constructor is called since you are not using a member initialization list the string member is default constructed. Then in the ctor body you are going assignment, not initialization. Only your first way actually intializes the variable with "test"
@NathanOliver can you offer an example please?
An example of what? The top two answers say the same thing.
|
1

You cannot initialize member in constructor body because it is already initialized at that point and syntax reflect that fact. That is already answered but I would like to point to another thing - improperly using terminology may lead to incorrect code. So some people say "you may initialize in constructor body by assignment". Why is this wrong? Let's look into this example:

struct foo {
    int i = 0;
    int &r = i;

    foo() {}
    foo( int &ref );
};

and you want r point to the same as ref if that ctor is called:

foo::foo( int &ref ) : r( ref )
{
}

now what will happen if you try to "initialize" by assignment:

foo::foo( int &ref )
{
    r = ref;
}

so now instead of pointing int reference r to the same int as ref you just assigned value to member i. This may lead to difficult to catch bugs and morale is: "terminology is important in programming, and you should not freely play with it"

Comments

1

test("asdf") is a function call and you cannot call strings like that. Initialization list ("Case 1") is a special case.

In the constructor body, just use assignment

test="asdf".

In this case, at first string test is default-constructed (becomes empty) and then a new string gets constructed and assigned to member test.

3 Comments

Technically that is not initializing since the string gets default constructed. It is assignment inside the ctor body.
Agree. changed my answer
Still sounds wrong "if you want to initialize then assign", no you cannot initialize that way. Though in this case result will be similar in many cases it will not work just because you cannot initialize this way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.