Reputation: 3478
Is the following well-defined?
std::vector<std::string> v{"test"};
v.assign(1, v.at(0));
If the old sequence was destroyed before the new one is constructed
the reference passed to assign
would be invalidated and hence the
program would be ill-formed.
Does the standard mention this case (the value being part of the old sequence) or something similar anywhere, making this construct well-formed? I couldn't find anything.
From the copy of Dinkumware's standard library implementation shipped
with VS2010 (_Assign_n
is what's called internally by assign
):
void _Assign_n(size_type _Count, const _Ty& _Val)
{ // assign _Count * _Val
_Ty _Tmp = _Val; // in case _Val is in sequence
erase(begin(), end());
insert(begin(), _Count, _Tmp);
}
The comment
in case _Val is in sequence
suggests that either the standard explicitly states that assigning an element that is part of the current sequence is well-formed, or that Dinkumware's implementation just tries to be smart ;)
Which one is it?
Upvotes: 11
Views: 312
Reputation: 20990
This is undefined behaviour, the copied element cannot come from the container itself.
[sequence.reqmts] table 84 (draft n4606)
Upvotes: 9
Reputation: 118300
at()
returns a reference to the existing value in the container. As such, this is undefined behavior.
You can make this well defined behavior simply by making a copy of it:
v.assign(1, (std::string)v.at(0));
Upvotes: 1