954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

How to initialize a vector?

I want a vector with some values by default. I wanted to do something like char **strings = {"bla", "blo"}

How to do it with vector<> without using repeated push_backs?

neithan
Junior Poster in Training
75 posts since Oct 2009
Reputation Points: 12
Solved Threads: 2
 

Unfortunately AFAIK push_back is the only way to initialize it. The vector is a single object, not an array of objects, so an initialization list is not possible.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

OK, push_back definitely is the safest way of populating a vector. However, the method I'm about to show is not particularly good practice, but it can be done and it does have it's uses:

#include<iostream>
#include<string>
#include<vector>


using namespace std;

int main()
{
	// here are our original strings in an array of strings
        // for the sake of this example imagine that strs[] was
	// passed in as an argument so we don't know upfront how 
        // many strings are in the array 
	string strs[] = {"String1","String2","String3","String4","String5"};

	// But before we attempt to reserve some space on a vector,
        // we need to know how many strings there are..... 
        // trying to count them doing something like this
	// int count=0;
	// while (strs[count])
	//     ++count;
	// 
	// Would not work as std::string cannot be evaluated like 
        // that...So we actually need to know upfront how many there are
	// in order to reserve space in the vector.
	int count=5; // so this value would have to be passed-in too!

	// reserve 'count' spaces in our vector
	vector<string> vec(count);

	// now our vector has enough space to hold all of the strings in the passed-in array....
    // so we'll set up a loop to copy strings from the array to the vector:
	for(int index=0;index<count; ++index)
	{
                // This can be used, but it is dangerous
		//vec[index] = strs[index];

                // This is safer..Less likely to cause a crash if you 
                // overstep the mark with index!
                vec.at(index]=strs[index];
	}

	// Now let's see what the vector contains
	cout << "The strings in the vector are:" << endl;

	for(vector<string>::iterator iter = vec.begin(); iter!=vec.end(); iter++)
	{
		cout << (*iter) << endl;
	}

        // enter any random string to quit!
	string dummy;
	getline(cin, dummy);
}


So vectors can be initialised in this way and this way of doing things can be useful, or may even be necessary from time to time, but you must know exactly how much space you need to reserve in the vector upfront. If you don't reserve enough space in the vector, then your program's almost certainly gonna crash!

But do use push_back wherever possible!
If you were to try to add more items once the vector was initialised in this way, I'd almost certainly use push_back!!

Cheers for now,
Jas.

JasonHippy
Master Poster
772 posts since Jan 2009
Reputation Points: 590
Solved Threads: 125
 

However, using push_back(), you'd do it like this:

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main()
{
	string strs[] = {"String1","String2","String3","String4","String5"};
    // we still need to know how many strings there are
	int count=5; 

	// no need to reserve any space in the vector 'cause we'll use push_back()
	std::vector<string> vec;

	// so lets populate the vector....
	for(int index=0;index<count; ++index)
	{
		vec.push_back(strs[index]);
	}

	// Now let's see what the vector contains
	cout << "The strings in the vector are:" << endl;

	for(vector<string>::iterator iter = vec.begin(); iter!=vec.end(); iter++)
	{
		cout << (*iter) << endl;
	}

	string dummy;
	getline(cin, dummy);
}


This is by far the preferred way of doing things!

Jas.

JasonHippy
Master Poster
772 posts since Jan 2009
Reputation Points: 590
Solved Threads: 125
 

Ballpark?

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
   string init[] = {"one", "two", "three", "four", "five" };
   vector<string> vec(init, init + sizeof init / sizeof *init);
   copy(vec.begin(), vec.end(), 
        ostream_iterator<string>(cout, "\n"));
   return 0;
}

/* my output
one
two
three
four
five
*/
Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 

Ballpark?

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
   string init[] = {"one", "two", "three", "four", "five" };
   vector<string> vec(init, init + sizeof init / sizeof *init);
   copy(vec.begin(), vec.end(), 
        ostream_iterator<string>(cout, "\n"));
   return 0;
}

/* my output
one
two
three
four
five
*/

Of course!
Good thinking...Dave, I'd not thought of that!
Nice use of the copy algortihm too...I'd forgotten about that little STL gem!

JasonHippy
Master Poster
772 posts since Jan 2009
Reputation Points: 590
Solved Threads: 125
 

would this do ?

string words[3] = {"hello","olla","namesta"};
	vector<string> vec(words,words+3);

	for(int i = 0; i < vec.size(); i++)
		cout<<words[i]<<endl;


[edit]
Oh, looks like someone already has gotten this answer
[/edit]

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

would this do ?

string words[3] = {"hello","olla","namesta"};
	<strong>vector<string> vec(words,words+3);</strong>

	for(int i = 0; i < vec.size(); i++)
		cout<<words[i]<<endl;

[edit] Oh, looks like someone already has gotten this answer [/edit]

I though it was vector name(lenght or size, init values);

So..typing words in the name... is that the memory direction of that array? You totally lost me on that one :S

neithan
Junior Poster in Training
75 posts since Oct 2009
Reputation Points: 12
Solved Threads: 2
 

I though it was vector name(lenght or size, init values);

So..typing words in the name... is that the memory direction of that array? You totally lost me on that one :S

Vectors has many constructors. See here, Link

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

Thank you for the link. What i've understood is you can "construct?" a vector in any of these 4 ways:

vector<int> v(); // a void v vector
vector<int> v(4, 100); // v is 100,100,100,100
vector<int> v(words, words + 3); copy each element of the array words, from the first to the third
vector<int> x(v); // x is a copy of v


Is that it?

neithan
Junior Poster in Training
75 posts since Oct 2009
Reputation Points: 12
Solved Threads: 2
 
Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 

The problem with Dave's suggestion is all those strings are now stored in memory twice -- once in the array of std::strings and again in the vector of strings. That could be a problem if the computer is low on memory, or the array contains thousands of strings. If there is an array of std::strings then there isn't much point to using a vector to hold the same strings.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 
The problem with Dave's suggestion is all those strings are now stored in memory twice -- once in the array of std::strings and again in the vector of strings. That could be a problem if the computer is low on memory, or the array contains thousands of strings. If there is an array of std::strings then there isn't much point to using a vector to hold the same strings.

And this differs from using push_back with some "default" strings how?

My "Ballpark?" example was how I understood the question neithan was asking:I want a vector with some values by default. I wanted to do something like char **strings = {"bla", "blo"}

How to do it with vector<> without using repeated push_backs?

Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 
And this differs from using push_back with some "default" strings how?

It doesn't -- unless the strings are read from a file, in which case your example wouldn't work either :)

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 
It doesn't -- unless the strings are read from a file, in which case your example wouldn't work either :)

No. But there are other methods that don't use push_back , like using a back_inserter with copy perhaps; or maybe something about writing an insert_iterator . :icon_wink:

Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 
If there is an array of std::strings then there isn't much point to using a vector to hold the same strings.

I agree but i've seen it in a lot of example codes. I asked in this forum if i should learn to use array or vector and i got a major answer of learning vector because it's standard (shall i say modern?) although not forgetting the array.

I think people would use Dave's suggestion to take the advantadges of vector but having it initialized somehow.

I'm surprised array can be inialized directly and vector not. That's kind of a weakness isn't?

neithan
Junior Poster in Training
75 posts since Oct 2009
Reputation Points: 12
Solved Threads: 2
 
I'm surprised array can be inialized directly and vector not. That's kind of a weakness isn't?

Arrays can suffer from the same copy penalty mentioned earlier -- a copy lying around for use in the initialization. For example:

int foo(int x)
{
    int array[] = {1,2,3,4,5};
    return array[x];
}

char *bar(int x)
{
    char *text[] = {"one","two","three","four","five"};
    return text[x];
}


Perhaps it's the "default values for a modifiable object" that seems to make more of an issue of it.

Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 

BTW, shouldn't:

char *bar(int x)
{
char *text[] = {"one","two","three","four","five"};
return text[x];
}

be char **bar(int x) ?

neithan
Junior Poster in Training
75 posts since Oct 2009
Reputation Points: 12
Solved Threads: 2
 

No.

Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You