0

I am new to C++. What does it mean exactly to "new" a collection? For example:

UnicodeStringList* tmp = new UnicodeStringList;
// where UnicodeStringList is typedef to std::list<UnicodeString>

When you "new" something you have to know exactly how big you need it to be, right? So when I use the assignment constructor to copy an object, how will the computer know how much memory should be allocated on the heap? For example:

*tmp = another_string_list;

another_string_list is being copied into my new'd UnicodeStringList in heap memory, but I never initially specified how big that heap memory ought to be. And the compiler doesn't know how big another_string_list is so how much memory goes into the heap?

I am confused and hopefully I've specified my question enough so someone may understand me, but I'm not sure.

Please help

Thanks,

Julian

trincot
  • 317,000
  • 35
  • 244
  • 286
jbu
  • 15,831
  • 29
  • 82
  • 105
  • 2
    I also want to question why you're heap allocating a list independently. Most people only need to use lists as a part of a greater object, and since you can change the contents of the list at any time, there's rarely need for directly heap allocating a container. – Puppy Jul 16 '10 at 18:09

6 Answers6

6

The size of a std::list doesn't change when you add elements to it. I'm going to use a std::vector because the example is simpler, but the same concept applies: a std::vector contains a pointer to an array, which is dynamically resized as needed to contain your elements. The pointer to the array doesn't change in size (it's the size of one pointer), even though the array it points to changes

Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
  • 4
    `std::list` is a double-linked list. A `std::vector` would be more appropriate for your example. – zneak Jul 16 '10 at 17:58
  • This. The list has a static size, however many items are in the list. – Puppy Jul 16 '10 at 17:59
  • @zneak Thanks; I'd just edited my answer to say that it probably doesn't actually use an array, but I changed it again to just use a vector in the example; that does make it easier to explain – Michael Mrozek Jul 16 '10 at 18:00
  • +1 for zneak - Michael, you should modify your answer accordingly. Edit... :) – Cam Jul 16 '10 at 18:00
  • OP here. Why would a vector be better than a list in my example? Any items I add to the collection are still going to be put on the heap, right? – jbu Jul 16 '10 at 18:04
  • @jbu: Linked lists and vectors have different times for different operations. For example, it's constant to access a vector- accessing the n'th vector is always the same time. A linked list increases as N increases, however. A vector is N to insert, but a linked list is constant. Etc. The two data structures have different times for different operations, and thus suited to different uses. – Puppy Jul 16 '10 at 18:06
  • @jbu It was better for my example, not necessarily for yours. It's easier to explain a collection that contains a single pointer than it is to explain a list, where the nodes have pointers to each other – Michael Mrozek Jul 16 '10 at 18:09
  • @jbu: Collections are different. Assuming you are new to C++, `vector`s should probably be more convenient for you. A `vector` is simply a wrapper over an array to make it extensible at will; a `list` is something completely different. Usually (but it depends on your needs, really) you'll prefer the `vector` over the `list`. – zneak Jul 16 '10 at 18:11
3

All that "new" does is allocate enough space to store all the member variables for your std::list. Anything extra that may need to be done is the std::list's business, and it should take care of that itself (via its constructors and destructors).

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
2

When you "new" something you have to know exactly how big you need it to be, right?

Not exactly. At least, not in the way that you're thinking about it.

When you new a raw array then of course you have to provide the number of elements in the array. But std::list, std::vector, and such are not raw arrays.

Taking std::list as an example: From the outside, you can think of it as something that contains whatever you put into it. However, in detail, it is an object that directly contains only pointers. Those pointers point to other objects that it has allocated on the heap (using new). Thus an instance of std::list itself is always the same size, however as you add more things to it, it will end up allocating more stuff elsewhere on the heap to manage it.

This is also why you can use a list as a stack-allocated local variable and not have trouble pushing any number of items into it.

UnicodeStringList MyList;
MyList.push_back(item1);
MyList.push_back(item2);

No need for new. The list arranges its own internal (heap allocated) bookkeeping to accommodate as my items and you want to add to it.

And so when one list A assigned to list B. All items (and any internally managed bookkeeping objects) from list A are copied into newly heap allocated items and given to list B to manage.

TheUndeadFish
  • 8,058
  • 1
  • 23
  • 17
1

The only place where you actually have to know how big something will be is on the stack. The stack must grow in a very statical way to please your compiler. The heap, however, has no such constraints.

When you new something, you allocate it on the heap. Therefore, it can be of any size. What surprises you should rather be that collections can also be allocated on the stack. This is because no matter what a collection contains, its size is invariant. Rather, it contains informations (like pointers) to the heap where the size of an allocation must be variant.

zneak
  • 134,922
  • 42
  • 253
  • 328
1

When you new and object, you get the memory that is required for that object in it's initial state. However, you need to realize that a class can implement quite a bit of complexity in how it deals with its internal state.

Specifically for your question, a class (in your case a list<>) can itself dynamically allocate and release memory during the course of it operations. And that's what your list collection will do - when an item is added to the list, it'll allocate memory for that item and perform whatever housekeeping is necessary to manage that new item, usually using pointers or smart pointer objects. So the memory used by the list<> object may change, but the 'core' list object itself remains the same size as when it was allocated originally.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

You might want to look up what new does. It puts it on the heap memory instead of stack memory. This way, it's not going to go away when you lose scope. It has nothing to do with the known size. You might be confusing this with arrays, where when you allocate the memory for an array you need to know the size, and you typically new it.

corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • Yeah I know that it goes onto the heap. Part of my question is: what are the consequences of that example code since I've told it to allocate heap memory but copy into it an object of an unknown size? – jbu Jul 16 '10 at 17:58