0

Long time java programmer here, new to C++. I have been working with C-style "traditional" arrays (similar to arrays in java). I understand in C++ we can create a simple array as follows:

Person people[3];

The contents of this array is essentially uninitialized junk values. When I print out the contents of each element in the array, I (believe) am getting the memory address of each element.

for(int i = 0; i < 3; i++){std::cout << &person[i] << std::endl;}

Results:

//Note, I get different results here when I use an enhanced for loop vs an iterator for loop. Weird.
00EFFB6C
00EFFBA8
00EFFBE4

Now, here is the part I have failed to get a clear explanation on. I create a pointer to one of the elements in the array. I then ask for some value back from that pointer. In java, I would expect to get a null pointer, but in C++, that is not happening.

Instead, I get the default value, as though this element is initialized:

Person* person1Ptr = &people[0];//Points to an uninitialized value
std::cout << person1Ptr->getFirstName() << std::endl;//Output: "Default First Name", expected nullptr

When I try to get the first name of an element using a reference, this doesn't work (presumably because the value doesn't exist).

Full paste of code: https://pastebin.com/cEadfJhr

From my research, C++ does NOT fill arrays with objects of the specified type automagically.

How is my person1Ptr returning a value?

11
  • typo, sorry - fixing now Commented Feb 16, 2021 at 15:28
  • 2
    In Person people[3]; the initial state of the 3 Person elements depend on what Person is. If it is a class type they will be default initialized. Whether or not that means there is uninitialized data depends on how Person is implemented. Commented Feb 16, 2021 at 15:28
  • 1
    "From my research, C++ does NOT fill arrays with objects of the specified type automagically." This is incorrect. Since you are coming from a Java background, you may have the preconception that Person is some form of handle to an instance of Person. In the case of Person people[3]; you have three actual instances of Person no matter what. What you may be thinking of is that C++ might not initialize those objects to a meaningful value. Whether or not that happens depends on the details of Person. Commented Feb 16, 2021 at 15:34
  • 2
    You should share a minimal reproducible example including a short definition for Person that produces the behavior you witnessed. It is difficult to answer the question specifically without knowing more about your test. Commented Feb 16, 2021 at 15:37
  • 1
    Person is a class type with a default constructor, so all three elements get default constructed. Commented Feb 16, 2021 at 15:46

1 Answer 1

4

I believe the problem stems from this misconception :

From my research, C++ does NOT fill arrays with objects of the specified type automagically.

C++ objects have value semantics. Defining a local variable of type T concretely creates a unique instance of that type, it is not a handle to a potential T. The expression Foo f; is conceptually equivalent to the Java expression Foo f = new Foo();. Additionally, value semantics means assignment usually implies a copy. The C++ expression Foo f; Foo g = f; is conceptually equivalent to the Java expression Foo f = new Foo(); Foo g = f.Clone();.

In the case of an array, defining a local variable Foo f[3]; immediately creates three instances of Foo as elements of the f array. Your misconception may come from the fact that creating an object in C++ does not imply that it has been initialized. An object can exist in an uninitialized state. For example int i; create an int object identified by i but its value is indeterminate. In the case of int i[3]; you would have an array of three int each with indeterminate values.

The rules for initialization are very complicated in C++. In the case of Person people[3]; you have an array that is default initialized.

You are initializing an object of type Person[3]. According to default initialization rules :

if T is an array type, every element of the array is default-initialized;

That means each Person gets its own default initialization. To see what happens, consider that T is Person :

if T is a class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;

So each Person's default constructor will be called to initialize that element. You end up with Person people[3]; defining three default constructed Person objects with default initial values.

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

4 Comments

In the first part, you mean Foo f = new Foo(); Foo g = f.clone(); in java, correct? Right now, you have it listed as Foo f = new Foo(); Foo f = f.clone(); Thank you for the clarification to C++ array object initialization. It does seem odd to me, however, that C++ would generate instances for each element in the array. Object instantiation for each element in the array could potentially result in large performance overhead, no?
@Matthew Yes, that was a typo. It was means to be Foo g = f.Clone(), which I've corrected in the answer.
@Matthew In C++, an array of objects is a collection of objects. If you write Foo f[3]; you tell the compiler "I want 3 Foo right now". If this is a performance problem, than you probably don't want to ask that and shouldn't use Foo[3]. If you instead want 3 handles to potential future instances, you can use something else. Maybe Foo* f[3];, std::optional<Foo> f[3], std::shared_ptr<Foo> f[3], std::unique_ptr<Foo> f[3] or any of countless other possibilities, including std::vector<Foo> f; which in most cases will be preferable to Foo f[3].
@Matthew Each approach is suitable for a different use case. The best approach depends on what you actually want to accomplish and the context in which you want to accomplish it.

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.