1

I read this from A tour of C++,

"Unlike an ordinary function, a constructor is guaranteed to be used to initialize objects of its class. Thus, defining a constructor eliminates the problem of uninitialized variables for a class."

How does this initialization work? E.g., suppose that I have a class with a field "s" of type string

class C{   
     std::string s;   
     ...

}

How does "s" get initialized, and would its value be guaranteed to be the empty string whatever the compiler?

10
  • 4
    What book are you using? This should be covered in a good C++ book Commented Dec 6, 2019 at 13:59
  • 1
    Note that there are plenty of on-line material about this topic, e.g. en.cppreference.com/w/cpp/language/initializer_list or en.cppreference.com/w/cpp/language/default_constructor Commented Dec 6, 2019 at 14:03
  • 1
    @Bob__ You should change your display name to __Bob, which would make your behavior undefined ;-) Commented Dec 6, 2019 at 14:05
  • 1
    @DanielsaysreinstateMonica Well, that's what I was trying to avoid, unsuccessfully I'm afraid ;) Commented Dec 6, 2019 at 14:08
  • 1
    @2785528 the default ctor provided does nothing — It doesn't do nothing. The compiler-provided default constructor default-constructs all subobjects, including s. Commented Dec 6, 2019 at 14:12

2 Answers 2

4

The passage means that, if you have an Initialise() function, someone might forget to call it. It is not "guaranteed to be used", because you cannot control people. On the other hand, you cannot "forget" to call a constructor, because you never call a constructor: the computer does that for you when you instantiate your object.

Of course, that doesn't mean that the constructor is guaranteed to be properly written; that's still down to you. In the case of a class like std::string, though, it's pretty hard to get that wrong as it'll at least be default-constructed if you do not write code to do something else instead.

That happens whether or not you have an Initialise() function that's supposed to be called later, but if you did put some more complex initialisation in your constructor then you can be assured that this code will run.

// Bad! People can forget to call Initialise, so the string might stay empty
class Foo
{
public:
    void Initialise(const bool yesOrNo)
    {
        m_string = (yesOrNo ? "Yes!" : "No");
    }

private:
    std::string m_string;
};

// Good! You'll always have a value; no way around that
class Bar
{
public:
    Bar(const bool yesOrNo)
       : m_string(yesOrNo ? "Yes!" : "No")
    {}

private:
    std::string m_string;
};

Further reading:

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

16 Comments

@user253751 but in practice, this allocates an object which is usable except for the fact the constructor is not called No, it doesn't. The only way to create an object in C++ is with a definition, by a new-expression, when implicitly changing the active member of a union, or when a temporary object is created. reference
@user253751 Well, you said it: undefined behaviour. I concede that my answer is predicated on the idea that you properly declare your object, and that there are still ways to cheat the system, but anyway I believe this is what the textbook is trying to get at. As for "in practice, this allocates an object which is usable except for the fact the constructor is not called", that's a belief you really need to get yourself out of. :)
@user253751 I believe you that it will compile, and may even appear to work. However, your definition of "usable" is, at best, optimistic. If you have this code in your project, you should fix it, or you will have a hidden bug. Never underestimate the compiler's drive to assume your program has no UB. You never created an object, so you're at risk of all sorts of weirdness. Remember, you're not programming a computer; you're describing a program, abstractly, and you must follow the rules laid out for doing so, unless you want pain.
@user253751 Reasoning about undefined behavior by observing expected behavior is nonsense. Even "this allocates an object" is incorrect. No object is allocated, just raw memory is allocated.
@user253751 I hope you don't work in a safety critical environment. UB in any form is just bad practice, even if the compiler does the sane thing. Not sure about you but having guaranteed behavior is what I always strive for.
|
1

When your instance of C is made, the std::string s is initialized in what is known as Member initialization.

How does "s" get initialized, and would its value be guaranteed to be the empty string whatever the compiler?

You're not showing us how you create C, so we don't know what constructor is used. If the default constructor is used, then the default constructor of std::string is used for s. This does indeed make an empty string, as explained here:

Default constructor. Constructs empty string (zero size and unspecified capacity).

Comments

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.