views:

131

answers:

6

Hi all,

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

A: 

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.

glowcoder
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
+5  A: 

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
`std::list` is a double-linked list. A `std::vector` would be more appropriate for your example.
zneak
This. The list has a static size, however many items are in the list.
DeadMG
@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
+1 for zneak - Michael, you should modify your answer accordingly. Edit... :)
Cam
@inc Good idea :P
Michael Mrozek
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
@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.
DeadMG
@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
@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
+1  A: 

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
+3  A: 

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.
+1  A: 

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
+2  A: 

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