1

I've seen a lot of similar questions regarding this topic, but I have seen no explicit answer to this question. Consider the following code:

typedef struct Student
{
    int id;
} Student;

vector<Student> students();
for( int i = 0; i < 10; i++ )
{
    Student s();
    s.id = i
    students.push_back( s );
}

How does this vector allocate memory? From my understanding, each Student s should have it's memory on the stack, and be de-allocated when the loop iterates, so this should produce undefined behaviour if I try and access this data later on. But if I had done the same thing with a vector<int> it would not produce undefined behaviour.

Is this correct? Either way, my goal is create a vector<Student> in which the objects are allocated on the heap, without having to use a vector<Student*>. Is this possible?

trincot
  • 317,000
  • 35
  • 244
  • 286
  • 3
    The objects are copied/moved to the vector. The way the vector handles its memory, those copies are most likely on the heap. – Blaze Dec 05 '19 at 08:05
  • 7
    Note that `vector students();` declares a *function* named `students`, which takes no arguments and return a `vector` by value. Drop the parentheses to define a vector object. – Some programmer dude Dec 05 '19 at 08:06
  • How does the compiler know how to copy a custom object? What about a full class with no copy constructor defined? – Jedediah Heal Dec 05 '19 at 08:07
  • Does this post give you some information: https://stackoverflow.com/questions/8036474/when-vectors-are-allocated-do-they-use-memory-on-the-heap-or-the-stack – wes Dec 05 '19 at 08:07
  • For most classes the compiler can generate a copy-constructor (as well as a copy-assignment operator) automatically if one isn't provided. If there isn't then it won't be able to copy the objects of the class and you will get a compiler error. – Some programmer dude Dec 05 '19 at 08:08
  • Yes I read that question before posting this, but it answers my question without explicitly answering how the compiler manages to move the memory from the stack (where the object was created) to the heap? – Jedediah Heal Dec 05 '19 at 08:09
  • 2
    `students` is on stack. The memory managed by it is on heap (`Student` elements). – zdf Dec 05 '19 at 08:10
  • 1
    @JedediahHeal The "stack" and the "heap" are not physically separated, they are just different areas of the same memory. The objects are copied, not moved or referenced. (C++ is not Java.) Copying an object from one part of memory to some other part is always the same. – molbdnilo Dec 05 '19 at 08:14
  • This uses the internally generated copy constructor when user defined is not there. Incase for a object if you need a deep copy, you should setup a copy constructor by yourself. – Destructor Dec 05 '19 at 08:20
  • 2
    Technically, there is no "heap" and "stack" in C++ at all. A `std::vector` employs dynamic memory allocation to manage a collection of objects, where the number of objects is determined at run time. Heap and stack describe details of how some, not all, implementations manage memory - and, on such systems, dynamic memory allocation often uses heap memory. – Peter Dec 05 '19 at 08:21
  • I would just add that when we say that an object is _copied/moved_ into a vector (when calling `push_back`), it is actually not copied per se. Only _its contents_ is copied/moved. Namely, in the vector-managed memory, a _new object_ is created, either by _copy/move constructor_. These constructors then perform the copy/move of the original object (`push_back` argument) contents. And, the original object stays where it was. – Daniel Langr Dec 05 '19 at 08:48
  • To declare a struct Student you should remove the "()" in students();, is not a class with a constructor. also in for loop, I guess you want to use students.push_back( s); – Math Lover Dec 05 '19 at 08:48

2 Answers2

3

According to vector in cppreference, a vector required two template parameters which are T (the type of elements in vector) and Allocator which is set by default to std::allocator<T> and according to std::allocator's allocate function, which will have to be called by vector in order to allocate memory:

Allocates n * sizeof(T) bytes of uninitialized storage by calling ::operator new(std::size_t) or ::operator new(std::size_t, std::align_val_t) (since C++17), but it is unspecified when and how this function is called. The pointer hint may be used to provide locality of reference: the allocator, if supported by the implementation, will attempt to allocate the new memory block as close as possible to hint.

So whenever there is no given allocator to vector, all the newly members are stored in heap. Although most of the allocators must be using heap to allocate memory.

rezaebrh
  • 424
  • 2
  • 6
  • 19
2

Create the std::unique_ptr<Student> ... Also use the std::vector<std::unique_ptr<Student>> type to hold the data. This way you do not have to worry about deleting the allocated memory on heap storage by unique_ptr.

Build Succeeded
  • 1,153
  • 1
  • 10
  • 24