3

C++:

Student* sp = new Student[10];

Now, please correct me if wrong. I believe this creates an array of 10 instances of Student, each calling the default constructor with no arguments.Please use arrays and not vectors.

Java:

Student [] sa = new Student[10];

Again, correct me if I'm wrong but I think in case of Java though, no instances are created when this statement executes and instead only memory is reserved to hold 10 references to Student instances. And it is necessary that we follow it up with:

sa[0] = new Student(*arguments*);
sa[1] = new Student(*arguments*);
.
.
.

sa[9] = new Student(*arguments*);

I'm trying to see the difference and quite frankly, I'm confused. Kindly clarify please.

8
  • 1
    You can't easily do that in C++. Using a vector is the answer (this becomes trivial), so it's a little pointless outright disallowing it. Commented Feb 28, 2015 at 0:53
  • 1
    I know but I'm trying to understand the concept of ARRAYS of Objects here. I may use Vectors but I want to have Arrays in my repertoire as well. Commented Feb 28, 2015 at 0:56
  • Can you see the difference I'm trying to highlight. In C++ they are instantiated whereas in Java, they are not. Is my understanding correct or am I horribly mistaken here? Commented Feb 28, 2015 at 0:58
  • Well, it's actually better C++ to not use any dynamic allocation, unless there's good reason. Commented Feb 28, 2015 at 0:59
  • 1
    Even though everyone will kill kittens if you use arrays in C++, there's nothing wrong with trying to understand how they work in the first place. Commented Feb 28, 2015 at 1:01

3 Answers 3

10

What do you mean, you're trying to see the difference and you're confused? The difference is exactly what you've stated. The C++ code creates an array of 10 Student objects that are default-initialized [1], and the Java code creates an array of 10 references so no Student constructors are called until you do it yourself.

Maybe your question is why C++ and Java differ. That's because a Student[] in Java is an array of Student references, so the true C++ equivalent would be an array of Student pointers,

Student** sp = new Student*[10]

which you would indeed have to follow up with

sp[0] = new Student(args);
...
sp[9] = new Student(args);

analogously to your Java example.

Now, if you want an array of 10 Student objects in C++ initialized using a constructor other than a default constructor, you have to do it in two steps: first allocate memory for 10 Student objects, then manually construct the Student objects over that memory using placement new. I do not endorse this style of coding. It is very confusing even to experienced C++ programmers.

typedef Student SA[10]; // SA means array of 10 Students
SA* psa = static_cast<SA*>(::operator new(sizeof(SA)));
SA& sa = *psa; // sa refers to an array of 10 Students
new (&sa[0]) Student(args); // construct the Student object
// ...
new (&sa[9]) Student(args);
// later
for (int i = 0; i < 10; i++) {
    sa[i].~Student(); // destroy the Student object
}
::operator delete(psa); // deallocate the memory for the array

Use a damn vector.

[1] Note: In C++, for a class, default-initialized means that the default constructor is called; for an array, it means each element is default-initialized; and for an arithmetic, pointer, reference, or enum type, it means it's not initialized at all.

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

4 Comments

btw, I have made several edits to the answer because I screwed it up the first few times. Tricky stuff. Better to just use vectors.
Please add a clarification what default-initialized means. Especially, that it need not be the same as calling the default-constructor. And for your last example, we have brace-and-init-initializers, which are better.
You should a clarification what a scalar type means as well.
Your first line of code is incorrect - did you mean: Student **sp = new Student*[10] ?
6

Short answer:

Those two declarations are different. The C++ one allocates an array of Student objects, while the Java one allocates an array of references to Student objects.

Long answer:

The difference is that, in Java when you declare an object:

Student s;

It creates a reference (similar to a pointer in C++) to a Student and initializes the reference to null. You can then later assign a Student object to that reference variable with s = new Student().

But in C++ when you declare an object:

Student s;

It creates an actual object (not a reference to an object as in Java). And thus the object must be immediately instantiated.


So in Java, when you do this:

Student [] sa = new Student[10];

It actually creates an array of references to Student objects (not an array of actual Student objects), and they are all initalized to null references.

...I think in case of Java though, no instances are created when this statement executes and instead only memory is reserved to hold 10 references to Student instances.

So yes, you're right.

But in C++ this:

Student* sp = new Student[10];

dynamically allocates an array of actual Student objects. Again, not references as in Java, so each object will be instantiated immediately.

I believe this creates an array of 10 instances of Student, each calling the default constructor with no arguments.

Correct as well.

So in Java after declaring the array of references you can then instantiate the actual objects and assign them to those references in the array with this:

sa[0] = new Student(*arguments*);

But in C++ the Student objects in the array were already instantiated, so this is not needed.


Bonus: Array of pointers in C++

In C++, you can also declare an array of pointers to postpone object instantiation, similar to the Java array of references:

Student** spp = new Student*[10];

This will create an array of 10 pointers to Student objects. You can then instantiate the objects when needed and assign their memory addresses to the pointers:

spp[0] = new Student(*arguments*);

This looks a lot like Java, but is actually not generally recommended in C++. In fact, using new in C++ should be avoided most of the time.

Comments

0

Here's a round about way of accomplishing what you are hoping to using the new operator.

#include <new>

struct Student
{
   Student(int ){}
};


int main()
{
   // Allocate memory for 10 Students.
   // Don't construct Student objects yet.
   char* cp = new char[10*sizeof(Student)];

   // Now construct the Student objects using
   // placement new
   Student* sp[10];
   for ( int i = 0; i < 10; ++i )
   {
      sp[i] = new (cp + sizeof(Student)*i) Student(10);
   }

   // Use the Student objects
   // ...
   // ...

   // Call the destructor on the Students explicitly.
   for ( int i = 0; i < 10; ++i )
   {
      sp[i]->~Student();
   }

   // Deallocate the memory.
   delete [] cp;
}

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.