3

I'm working with vector now and I have an interesting situation which I need to help with.

I have a vector of vectors, defined as following:

vector< vector<int> > list;

I am loading numbers from standard input using cin >> helpVar; and everytime when I get 0 (zero) I want to create new vector of ints, which will be put into this "main container" list.

Of course I don't know, how many times the zero number will appear - it's user-dependend. So I also don't know, how much vectors the program will add.

But I don't know, how exactly to do it. If I used C# or other garbage collection-like language, I would probably just write:

if(helpVar == 0)
{
   list.push_back(new vector<int>);
}

But this construction doesn't work in C++.

So my question is, how should I deal with this situation to make it working? Or am I just thinking about it wrong and it should be done in another way?

Thanks for the answers.

Tamás Szelei
  • 23,169
  • 18
  • 105
  • 180
Miroslav Mares
  • 2,292
  • 3
  • 22
  • 27
  • For the record, it would work if you have a vector if pointers to vectors. It simply wouldn't be idiomatic (avoid `new` whenever you can). –  Nov 14 '11 at 18:16
  • Beware of the danger of memory leaks when doing this. See: http://stackoverflow.com/questions/307082/cleaning-up-an-stl-list-vector-of-pointers – Raedwald Nov 14 '11 at 18:20
  • @delnan This is actually bad advice. Don't "avoid `new` whenever you can" because doing so will often require copying which can be expensive. Each language construct has it's advantages so use them wisely and forget "always" rules. – Giovanni Funchal Nov 14 '11 at 18:22
  • @GiovanniFunchal: That's very debatable. There are plenty of C++ idioms that are entirely efficient *and* safe, all of which "avoid `new` whenever possible". – Kerrek SB Nov 14 '11 at 18:24
  • @GiovanniFunchal: Apart from what Kerrek said, consider: Excessive copying, should it turn out to be a show stopper for performance, can be remedied easier than a memory management mess (be it leaks or any kind of UB). It becomes far easier with smart pointers, but then again, 2/3 "C++" programmers seem to be unable to use those... –  Nov 14 '11 at 18:31
  • I'd just say that maybe smart pointers are NOT the best solution 2/3 of the time? :) – Giovanni Funchal Nov 14 '11 at 18:45

5 Answers5

7
list.push_back(vector<int>());

vector<int>() creates a temporary vector<int> object and initializes it (i.e., it calls the default constructor for that object). push_back then copies that temporary object into the list.

In C# (and "other garbage collected languages"), new is used to create new objects, whose lifetimes are controlled by the garbage collector.

In C++, new is only used to dynamically allocate an object (and you are responsible for managing its lifetime, by using a smart pointer). The syntax T() (where T is the name of a type) is used to create a temporary object.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 1
    In contemporary C++, you can even say `list.emplace_back()` for a minimal amount of overhead and typing. – Kerrek SB Nov 14 '11 at 18:25
3

In C++11:

list.emplace_back();

In C++03:

list.push_back(std::vector<int>());

new dynamically allocates an object and gives you a pointer to it; vector::push_back() takes a reference to an object, which it will copy. Only use new when you want to dynamically allocate the object yourself - that's not necessary if you're using containers to do that for you. When you do use new, make sure you use a smart pointer (or very carefully written code) to delete it when you've finished with it.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

You can

list.push_back(vector<int>());

in the beginning, add helpVar to the most recent vector by doing

list.back().push_back(helpVar);

and when you get a 0 just push back yet a new vector.

Vlad
  • 18,195
  • 4
  • 41
  • 71
1

In C++ you can just do:

x.push_back(T);

Memory management is done by the class itself. I hope I did understand you right.

One thing you have to look for is, if the class you are pushing back has a default constructor declared.

Stephan Dollberg
  • 32,985
  • 16
  • 81
  • 107
1

Just do

list.push_back(vector<int>());

If you say "new", you are asking for space in the heap, but you don't need that. You already have space reserved in the outer vector! Just push a vector object (not pointer) and you'll be done!

Advanced: Note that this actually first constructs a new vector in the outer vector by growing its size by 1, then creates a new temporary vector in the stack, then copies the content of the later (empty, so nothing to do) to the first, then destroys the temporary vector in the stack. But the compiler will probably optimize this completely!

Giovanni Funchal
  • 8,934
  • 13
  • 61
  • 110