Reserve vector with 100 strings each of fixed size 20

D

Diwa

I know I can reserve space for 100 strings in a vector by doing
following:

std::vector<std::string> m_vec;
m_vec.reserve(100)

But I also know that each of the string will be exactly 20 chars.
Can I use this fact while reserving the vector space above?
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
I know I can reserve space for 100 strings in a vector by doing
following:

std::vector<std::string> m_vec;
m_vec.reserve(100)

But I also know that each of the string will be exactly 20 chars.
Can I use this fact while reserving the vector space above?

Yes. You don't have to create an empty vector, and then resize it to
get the size you want either -- you can pass the size you want when
you create it:

std::string prototype(20, ' ');
std::vector<std::string m_vec(100, prototype);

This starts by creating a string of 20 space characters. It then
creates a vector of 100 copies of that string (and if you were to
resize the vector larger, those new strings would also be copies of
the 20-space string).
 
V

Victor Bazarov

Diwa said:
I know I can reserve space for 100 strings in a vector by doing
following:

std::vector<std::string> m_vec;
m_vec.reserve(100)

But I also know that each of the string will be exactly 20 chars.
Can I use this fact while reserving the vector space above?

Not really.

'reserve' doesn't create any elements. It only allocates memory where
the elements will be later created, usually by means of 'placement new'.
If you need to create a vector of 100 strings, and each string to have
20 chars, you need to use 'resize' or construct it directly:

std::vector<std::string> m_vec;

... /* initializer list */ m_vec(100, std::string(20, 0)) ...

or

m_vec.resize(100, std::string(20, 0));

The reason for this most likely that 'std::string' has its own memory
management which isn't "activated" until the object is constructed.
And, as I mentioned, 'reserve' does not construct elements.

V
 
J

Juha Nieminen

Diwa said:
I know I can reserve space for 100 strings in a vector by doing
following:

std::vector<std::string> m_vec;
m_vec.reserve(100)

But I also know that each of the string will be exactly 20 chars.
Can I use this fact while reserving the vector space above?

If you know that all the strings will be exactly 20 chars, and
especially if you know that will not change, you can use a char array
instead. Of course arrays cannot be used directly with std::vector, but
they can if you enclose them in a struct, like this:

struct My20CharString
{
char str[21];
My20CharString(): str() {}
};

std::vector<My20CharString> m_vec;
m_vec.reserve(100);

If you don't like having to write "m_vec.str" instead of just
"m_vec", then you could do this:

struct My20CharString
{
char str[21];

My20CharString(): str() {}
operator const char*() const { return str; }
operator char*() { return str; }
};
 
J

James Kanze

(e-mail address removed)>, (e-mail address removed)
says...
Yes. You don't have to create an empty vector, and then resize
it to get the size you want either -- you can pass the size
you want when you create it:
std::string prototype(20, ' ');
std::vector<std::string m_vec(100, prototype);

That's not quite the same thing as he wrote (although it might
be more appropriate). His code still constructs an empty
vector; it just guarantees that this vector will not require
reallocation before 100 elements are inserted.

If his goal is to avoid invalidating any iterators during a
push_back, that's all he needs. If his goal is to avoid any
further memory allocations, including for the strings, it
doesn't work. But I'm not sure why that would be a goal; if
he's using std::string, each string instance will allocate
memory separately from the vector, so creating them all up front
doesn't reduce the actual number of allocations, nor the
fragmentation. For that, he'd need some sort of fixed length
This starts by creating a string of 20 space characters. It
then creates a vector of 100 copies of that string (and if you
were to resize the vector larger, those new strings would also
be copies of the 20-space string).

Huh. Only if you used m_vec.resize( larger, prototype ).
 
J

Jerry Coffin

[ ... ]
That's not quite the same thing as he wrote (although it might
be more appropriate). His code still constructs an empty
vector; it just guarantees that this vector will not require
reallocation before 100 elements are inserted.

Yup -- I misread his code as using resize() instead of reserve()...

[ ... ]
Huh. Only if you used m_vec.resize( larger, prototype ).

Yup -- I originally intended something more like "...if you want to
resize the vector larger, those new string could also..." but mis-
spoke (so to speak).

My apologies for the incorrect information.
 
D

Diwa

(e-mail address removed)>, (e-mail address removed)
says...
Yes. You don't have to create an empty vector, and then resize
it to get the size you want either -- you can pass the size
you want when you create it:
std::string prototype(20, ' ');
std::vector<std::string m_vec(100, prototype);

That's not quite the same thing as he wrote (although it might
be more appropriate).  His code still constructs an empty
vector; it just guarantees that this vector will not require
reallocation before 100 elements are inserted.

If his goal is to avoid invalidating any iterators during a
push_back, that's all he needs.  If his goal is to avoid any
further memory allocations, including for the strings, it
doesn't work.  But I'm not sure why that would be a goal; if
he's using std::string, each string instance will allocate
memory separately from the vector, so creating them all up front
doesn't reduce the actual number of allocations, nor the
fragmentation.  For that, he'd need some sort of fixed length
string (template< size_t length > class String?) which uses a
char data[ length ] (or a boost::array) in its implementation.

OP here. Thanks to all who responded so far. Reserving space for
vector (its actually for one million strings and not 100 strings)
helps me to avoid copying and destroying till reserved capacity. But
from the post above, I realized that doing the same (i.e. reserving
space) for strings does not really serve any purpose.
 
D

Diwa

Diwa said:
I know I canreservespace for100stringsin avectorby doing
following:
std::vector<std::string> m_vec;
m_vec.reserve(100)
But I also know that each of the string will be exactly 20 chars.
Can I use this fact while reserving thevectorspace above?

  If you know that all thestringswill be exactly 20 chars, and
especially if you know that will not change, you can use a char array
instead. Of course arrays cannot be used directly with std::vector, but
they can if you enclose them in a struct, like this:

struct My20CharString
{
    char str[21];
    My20CharString(): str() {}

};

std::vector<My20CharString> m_vec;
m_vec.reserve(100);

  If you don't like having to write "m_vec.str" instead of just
"m_vec", then you could do this:

struct My20CharString
{
    char str[21];

    My20CharString(): str() {}
    operator const char*() const { return str; }
    operator char*() { return str; }



};- Hide quoted text -

- Show quoted text -



Thanks Juha. Seems like I will go this route of a struct containing
char[21] because we want to persist info to disk
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top