Sign in to follow this  
Telastyn

[STL] Why does this not work again?

Recommended Posts

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

using namespace std;

int main(){

string                  st="foo";
vector<string>          x;

x.reserve(1);
x[0]=st;
cout << x[0] << "\n";
}

cores with a segmentation fault on the assignment, 3 levels deep in std::string calls. I do this same sort of thing with associative containers without any problem. Even doing this after pushing something onto x works fine. I thought it might just need the reserve() but no luck. What little boneheaded thing am I forgetting or ignorant of?

Share this post


Link to post
Share on other sites
Because reserve() and resize() play different roles. After reserve(), you do have memory to hold the string object, but it hasn't been initalized. The assignment operator does assume that its target is a valid object. Since you used reserve() and not resize(), which would have actually created a string object in the allocated memory (and set the size of the vector appropriately), the assignment operator fails to work and you get a segmentation fault (probably related to the char* that a string object is supposed to contain).

Share this post


Link to post
Share on other sites
Heh. Fair enough. So why does the same thing, albeit with int's work:

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

using namespace std;

int main(){


vector<int> x;
int st=42;

x.reserve(1);
x[0]=st;
cout << x[0] << "\n";


}



just one of those happy coincidences that it actually does work, since it should die like the string version?

Share this post


Link to post
Share on other sites
I wouldn't rely on that. you are most likely going out of bounds.
cout << x.at(0) << "\n";

would changing it to that cause it to exit?

a vector might treat an int differently because storing a bunch of pointers to int would be pretty wasteful. just because it doesn't crash doesn't mean it is correct :)

Share this post


Link to post
Share on other sites
Should I read all of the explanations here? And what does a Standard Template Library do? What is it? It is obviously a library of standard templates... but what is it really.

Share this post


Link to post
Share on other sites
std::vector::reserve preallocates a chunk of uninitialized memory, enough memory for specified number of elements, The advantage of this function is that if optimal code is a necessity and the user can determine the number of elements that will be required, the user can reserve the memory in advance, and thus prevent a possible reallocation of memory and copying of vector data.

So basically in your case the vector's capacity is one but the size is still zero (you can check this with std::vector::capacity). You need to initialize the element via push_back/front which basically boils down to an in-place copy construction on the uninitialized element.

[Edited by - snk_kid on June 11, 2005 6:55:36 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by nprz
I wouldn't rely on that. you are most likely going out of bounds.
cout << x.at(0) << "\n";

would changing it to that cause it to exit?

a vector might treat an int differently because storing a bunch of pointers to int would be pretty wasteful. just because it doesn't crash doesn't mean it is correct :)


Ah, yes, the change does blow it up.

It was just confusing, since I tried with ints to see if it was a problem with string use or with vector use. Since the ints worked, I spent a bunch of time trying to figure out what was wrong with elementary string use...

Share this post


Link to post
Share on other sites
Quote:
Original post by fuchu
Should I read all of the explanations here? And what does a Standard Template Library do? What is it? It is obviously a library of standard templates... but what is it really.


It is a lot of data structures that make your life easier with C++, so you don't have to reinvent the wheel for basic stuff. It also has a lot of functions such as sorting.
It is just a template so that it will work with different types of data: int, float, string, user defined classes.

If you know a lot about data structures, then STL is easy to understand, otherwise that might be something to study first.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Quote:
Original post by nprz
I wouldn't rely on that. you are most likely going out of bounds.
cout << x.at(0) << "\n";

would changing it to that cause it to exit?

a vector might treat an int differently because storing a bunch of pointers to int would be pretty wasteful. just because it doesn't crash doesn't mean it is correct :)


Ah, yes, the change does blow it up.

It was just confusing, since I tried with ints to see if it was a problem with string use or with vector use. Since the ints worked, I spent a bunch of time trying to figure out what was wrong with elementary string use...


I have made that mistake before as well. I usually use the at function with vectors since I'd rather have it crash and be able to trace it than overwrite something it isn't supposed and keep running (although possibly abnormally).

reserve() just makes the capacity at least that size, so if you do a lot of insert it will not have to resize and copy data over and over again. resize fills the data in the vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by nprz
Quote:
Original post by fuchu
Should I read all of the explanations here? And what does a Standard Template Library do? What is it? It is obviously a library of standard templates... but what is it really.


It is a lot of data structures that make your life easier with C++, so you don't have to reinvent the wheel for basic stuff. It also has a lot of functions such as sorting.
It is just a template so that it will work with different types of data: int, float, string, user defined classes.

If you know a lot about data structures, then STL is easy to understand, otherwise that might be something to study first.


Are you talking about C++ structs? I know them pretty good. And what is a vector?

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
It was just confusing, since I tried with ints to see if it was a problem with string use or with vector use. Since the ints worked, I spent a bunch of time trying to figure out what was wrong with elementary string use...


Yes it would work because ints are POD-types and std::basic_string is not, since std::vector separates allocation/deallocation and construction/destruction for efficiency, std::vector::reserve deals with allocation only.

For non-POD types constructor needs to been invoked on the the uninitialized memory as not only does it initialize it, typically special set-up code is run but you don't do this yourself as std::vector handles it when you do say push_back/front, this is what you can logically think is going on:


#include <cstddef>
#include <new>
#include <string>

using std::string;

//....
std::size_t N = ...;

string* v = static_cast<string*>(::operator new(sizeof(std::string) * N)); //allocates only

::new(&v[0]) string("foo"); // placement new, constructs 1 element only

// ... you can now use element 1.

v[0].~string(); // destroys 1 element only

::operator delete(v); // deallocates only


You don't need to invoke constructors for POD-types, and they don't have destructors (or they are trivial destructors) so you dont invoke them (or you don't need to in the case of trivial destructors).

I guess i've come into this abit to late [grin].

[Edited by - snk_kid on June 11, 2005 6:08:38 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this