2

I think I have a basic problem of understanding instantiating objects from classes or rather storing them in variables / arrays.

I have a class

class sensor{
  public:
  // Constructor
  sensor() {
    isObject = true; // Define that an object has been instantiated
  }

  bool isObject = false; // By default set this property to false
};

and an array

sensor sensorList[5];

I thought that the defined array is only reserving as much memory as it is necessary for storing the maximum amount of possible elements (of type sensor, so here 5 x 1 Byte for the property isObject).

But if I Serial.println e.g. sensorList[1].isObject I get 1 as result, so the object has already been "instantiated" (= the constructor has obviously been called) without any explicit sensor sensor1;. Can someone please explain me why?

8
  • Non-instantiated objects aren’t a thing in C++. If something is an object, it’s instantiated. Uninitialised memory has no associated object type and can’t be accessed, except to instantiate objects. Commented Jan 25, 2020 at 12:11
  • if you put something such std::cout <<"sensor constructor\n"; within sensor ctor you will see it called 5 times Commented Jan 25, 2020 at 12:15
  • sensor sensorList[5] will default-construct (i.e. call the constructor that can accept no arguments) each of the five elements of the array. Commented Jan 25, 2020 at 12:24
  • @George That’s not true. C++ doesn’t use the terminology “primitive type”, and you can can have class types that aren’t default constructed upon initialisation. Commented Jan 25, 2020 at 12:27
  • @KonradRudolph C++ doesn’t use the terminology “primitive type” And neither did I :) George did Commented Jan 25, 2020 at 12:31

2 Answers 2

2

When you write:

void f() {
    sensor sensorList[5]; // [1]
}

The compiler will reserve sizeof(sensor) * 5 bytes in the stack and call five times the default constructor sensor::sensor() at line [1], once for each of the objects.

Can someone please explain me why?

Since it is what you almost always want, the language was designed that way. You can still separate the two steps in C++, but it requires different syntax (placement new) which is very rarely used unless you are designing containers, for instance.

The alternative would be to require developers to be always explicit about those two steps, which would increase the lines of code (and therefore bugs too).

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

2 Comments

To OP, for reference about placement-new, search for T* tptr = new(ptr) T; in en.cppreference.com/w/cpp/language/new
Actually the separation is what I wanted (mainly because of my misunderstanding) but I can simply add a method to set the variable isObject manually to true.
1

sensor sensorList[5]; is not only reserving memory, it is creating the objects using the default constructor, take the code:

int main()
{
    sensor sensorList[5];
    std::cout << sensorList[3].isObject;
    return 0;
}

It's almost instinctive to a C++ programmer that this will definitely work, and indeed it does. The objects were constructed using the only one you have in your class, thus the default constructor, so the output will be 1, true, had you not a constructor it would use it's own default constructor, in this case setting the variables to it's value, isObject would be 0, false.

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.