|
-
March 28th, 2010, 09:31 AM
#1
Selfappending vector
Hello,
I've got a strange problem:
#include <vector>
#include <iostream>
#include <string>
int main(){
std::vector<std::string> strvec;
strvec.push_back("A");
strvec.push_back("B");
strvec.push_back("C");
strvec.push_back("D");
strvec.push_back("E");
std::vector<std::string>::size_type i = strvec.size()-1;
for(;i>0;--i)
strvec.push_back(strvec[i-1]);
for each(std::string str in strvec)
std::cout << str << ',';
return 0;
}
Gives me;
A,B,C,D,E,D,,B,A
What am I doing wrong?
-
March 28th, 2010, 09:33 AM
#2
Re: Selfappending vector
You have a vector containing only std::strings and you asked to get every std::string out of strvec here
Code:
for each(std::string str in strvec)
std::cout << str << ',';
That is what you are doing wrong. What do you exactly want to do?
-
March 28th, 2010, 09:46 AM
#3
Re: Selfappending vector
Thats even stranger. The origenal program is longer than this example.
In the original A,B,C and D are "real" strings.
A for example is X10, B is pauze, C is Y20, D is pauze and E is X-20.
In my program I would like the resulting vector to contian;
("X10","pauze","Y20","pauze","X-20","pauze","Y20","pauze","X10")
But the resulting vector in my program contains;
("X10","pauze","Y20","pauze","X-20","pauze","","pauze","X10")
Thanks for the fast reply, btw.
-
March 28th, 2010, 09:58 AM
#4
Re: Selfappending vector
Give me a second, ill try to fix it myself first then explain it to you.
Well, the output at me is
 Originally Posted by Output
A,B,C,D,E,D,C,B,A
o_o.
-
March 28th, 2010, 01:19 PM
#5
Re: Selfappending vector
Nope, keep having this problem. Maybe it's my intel atom, or it's because I'm using visual studio 2008.
However...
for(;i>0;--i){
std::string str = strvec[i-1];
strvec.push_back(str);
}
works.
Thank you very much.
-
March 28th, 2010, 01:24 PM
#6
Re: Selfappending vector
 Originally Posted by po0ky
for each(std::string str in strvec)
std::cout << str << ',';
return 0;
}
Gives me;
A,B,C,D,E,D,,B,A
What am I doing wrong?
Use your debugger. What does the vector actually contain? Does it have the items?
Regards,
Paul McKenzie
-
March 28th, 2010, 04:47 PM
#7
Re: Selfappending vector
No, according to the debugger the vector holds all the items the cout is giving me.
Pynolathgeen seems to get the expected results.
Thats why I think its a bug in my compiler.
@Pynolathgeen what compiler are you using?
-
March 28th, 2010, 09:37 PM
#8
Re: Selfappending vector
 Originally Posted by po0ky
No, according to the debugger the vector holds all the items the cout is giving me.
Pynolathgeen seems to get the expected results.
Thats why I think its a bug in my compiler.
I don't think it's a bug in the compiler at all. Take a look at this line of code carefully:
Code:
strvec.push_back(strvec[i-1]);
Do you see the problem with this line of code? The problem is that you're modifying the vector that you're reading from. The push_back() takes a reference to the item to add. You are giving a reference, but at the same time, you're changing the container that gives you that reference. Therefore the behaviour is undefined.
For example, what if adding an item causes a reallocation to occur? That reference you passed is no longer valid, and I have a suspicion this is the reason why your code didn't work -- a reallocation was done, the reference is refering to junk, and you get a blank that is added.
So the bottom line is that there is no such thing as a "self-appending vector" in the sense that you can't call push_back() with a reference to one of the vector's items.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; March 28th, 2010 at 09:49 PM.
-
March 29th, 2010, 08:39 AM
#9
Re: Selfappending vector
 Originally Posted by Paul McKenzie
Do you see the problem with this line of code? The problem is that you're modifying the vector that you're reading from. The push_back() takes a reference to the item to add. You are giving a reference, but at the same time, you're changing the container that gives you that reference. Therefore the behaviour is undefined.
For example, what if adding an item causes a reallocation to occur? That reference you passed is no longer valid, and I have a suspicion this is the reason why your code didn't work -- a reallocation was done, the reference is refering to junk, and you get a blank that is added.
So the bottom line is that there is no such thing as a "self-appending vector" in the sense that you can't call push_back() with a reference to one of the vector's items.
Good point, though it seems to me that the conclusion is rather pessimistic. Wouldn't this be okay?
Code:
strvec.push_back(string(strvec[i - 1]));
But taking another look at the problem, it seems that the aim is to insert to the same vector the elements of the vector starting from the second last element to the first element. Keeping in mind that reallocation could be a problem, would this solution be feasible?
Code:
strvec.reserve(strvec.size() * 2 - 1);
strvec.insert(strvec.end(), strvec.rbegin() + 1, strvec.rend());
As long as strvec has at least one element, I think that the above snippet should work.
-
March 29th, 2010, 10:22 AM
#10
Re: Selfappending vector
 Originally Posted by laserlight
Good point, though it seems to me that the conclusion is rather pessimistic. Wouldn't this be okay?
This should work.
You use the reference to create a temporary string object (safe)
You use the temporary string object to add to a vector (safe)
the fact it's the same vector in this case isn't a problem anymore. At the moment you do the add, the reference used to create the temporary string will be invalid, but you have made a copy of the contents.
would this solution be feasible?
Code:
strvec.reserve(strvec.size() * 2 - 1);
strvec.insert(strvec.end(), strvec.rbegin() + 1, strvec.rend());
It will probably appear to work. But I'm not sure it's guaranteed (but my experience with stl isn't perfect).
if I read the documentation for reserve(), it would appear it's valid to implement this by making sure you have the required storage (by allocating a new location for the aray), but not actually copy the array to the new location until necessary.
-
March 29th, 2010, 11:10 AM
#11
Re: Selfappending vector
In practice, I think the reserve method will work, however ...
Concening the last 2 arguments, according the standard, the
pre condition for the last two arguments is that they are not
iterators into the vector (Table 67)
-
March 29th, 2010, 11:21 AM
#12
Re: Selfappending vector
Indeed. So, does the motivation behind that pre-condition also invalidate the use of std::copy with std::back_inserter?
-
March 29th, 2010, 05:28 PM
#13
Re: Selfappending vector
There I go blaming the compiler again. Thanks Paul McKenzie I think I understand the problem better now.
 Originally Posted by laserlight
Good point, though it seems to me that the conclusion is rather pessimistic. Wouldn't this be okay?
Code:
strvec.push_back(string(strvec[i - 1]));
I think this would be a good solution, if not the only solution.
I'll try it right away.
-
March 30th, 2010, 04:21 AM
#14
Re: Selfappending vector
You could also do this using a second, temporary vector:
Code:
vector<string> vec, temp;
vec.push_back("A");
vec.push_back("B");
vec.push_back("C");
vec.push_back("D");
vec.push_back("E");
copy(vec.rbegin()+1, vec.rend(), back_inserter(temp));
vec.insert(vec.end(), temp.begin(), temp.end());
copy(vec.begin(), vec.end(), ostream_iterator<string>(cout, " "));
Output is
-
March 30th, 2010, 06:26 AM
#15
Re: Selfappending vector
 Originally Posted by cilu
You could also do this using a second, temporary vector:
If you want to involve a second vector, then I suggest declaring temp near first use:
Code:
vector<string> vec;
vec.push_back("A");
vec.push_back("B");
vec.push_back("C");
vec.push_back("D");
vec.push_back("E");
vector<string> temp(vec.rbegin() + 1, vec.rend());
vec.insert(vec.end(), temp.begin(), temp.end());
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|