3

Consider the below program:

#include <string>
#include <iostream>

class B {
  private:
    std::string s;

  public:
    B() { s = fun(); }
    std::string fun() { return "hello"; }
    void print() {
        std::cout << s;
    }
};

int main(){
    B b;
    b.print();
}

The output is Hello

My Questions are:

  1. In which sequence memory is allocated for data members('s' in this case).
  2. Does Object exist while calling fun() in the constructor.

My doubt is how I am calling a function on the b object which is not yet created by the constructor.

9
  • 1
    "My doubts is how am i calling a function on the 'b' object which is not yet created in the constructor." What makes you think it wasn't created? Commented Aug 22, 2018 at 10:40
  • 2
    For completeness also consider this alternative: B() : s(fun()) {} Commented Aug 22, 2018 at 10:41
  • 3
    @SPlatten 1) C++ standard doesn't define stack, nor heap. It's just a implementation detail, which, technically, can be different between compilers. 2) "Global data is created on the heap." What makes you to say so? Commented Aug 22, 2018 at 10:56
  • 2
    @SPlatten - C doesn't define it either... Commented Aug 22, 2018 at 11:00
  • 1
    @SPlatten No it doesn't. And, no, it isn't. C++ standard only defines "storage duration", and the expected behavior for each storage duration. How, exactly, it is implemented, is up to a specific compiler. If you are certain that it defines what a stack, and heap is (without talking about std::stack and family), please, provide me with a chapter in a standard, where it is done so. Commented Aug 22, 2018 at 11:04

4 Answers 4

5

By the moment object's constructor body starts executing, all the object's bases, direct, or, consequently, indirect, and members have already been initialized, either explicitly or implicitly. So s is a valid string object that can be quite legally a LHS of an assignment.

One thing should probably be noticed here is, if you call a polymorphic class's virtual method from your constructor, then this, current, type's implementation is chosen, as any derived type has not been initialized yet so its overloads, if any, would be illegal to call.

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

Comments

0
  1. In which sequence memory is allocated for data members('s' in this case).
  2. Does Object exist while calling fun() in the constructor.

To answer your questions, let us consult the CPP standard (N4713). See the highlighted portion below:

15.6.2 Initializing bases and members
...
13. In a non-delegating constructor, initialization proceeds in the following order:
(13.1) — First, and only for the constructor of the most derived class (6.6.2), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
(13.2) — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
(13.3) — Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
(13.4) — Finally, the compound-statement of the constructor body is executed.

(13.3) answers 1. and (13.4) answers 2. By the time the constructor body is entered all non-static data members are initialized.

Comments

0
  1. In which sequence memory is allocated for data members('s' in this case).

Objects are always stored in a contiguous block of memory that cannot be resized. Therefore all sub-objects are allocated simultaneously when the super-object is allocated.

Note that an object like std::string may also allocate a dynamic memory buffer which is separate from the memory of the object itself. The earliest time this memory can be allocated is within the constructor of the string. That said, an empty string needs no buffer, so that allocation can be delayed until later.

  1. Does Object exist while calling fun() in the constructor.

No. The object doesn't exist completely yet. All of its memory has been before the constructor, and all of the sub objects will have been completely constructed before the constructor of the object. But the life time of an object starts when the constructor has finished. That said:

My doubt is how I am calling a function on the b object which is not yet created by the constructor.

It is fine to call member functions within the constructor.

You just have to make sure to not do anything that would rely on the constructor having been already executed, since it hasn't yet been executed. For example, if you specify a class invariant, that is established by the constructor, you then mustn't call any function that relies on that invariant before the invariant has been established.

Note that member functions can also be called from the member initialization list. There, some sub-objects have not been initialized yet, so great care must be taken to not call such member functions that would access the uninitialized sub-objects.

Comments

0

My doubt is how I am calling a function on the b object which is not yet created by the constructor.

It is already created.

All members are created before your constructor body begins.

Otherwise the constructor body would be useless!

On a philosophical point, this is why we should never say that B b "calls the constructor" (and this is particularly important when you're creating a temporary, like B(), which sort of looks like calling a function/constructor) … because, although the constructor is obviously involved, other stuff happens too, and some/most of it happens first.

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.