I want a vector<string> 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?

Recommended Answers

All 18 Replies

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.

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.

commented: Yes, that will work too. +24

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.

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
*/
commented: Of course...Nicely done Dave! +1

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!

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]

would this do ?

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

	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<type> 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

I though it was vector<type> 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

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?

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.

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<string> 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?

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 :)

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:

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?

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.

BTW, shouldn't:

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

be char **bar(int x) ?

No.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.