Why does valarray assignment not resize assignee per the documentation?
Asked Answered
T

1

5

Code:

#include <valarray>
#include <iostream>    

using namespace std;

int main()
{
  valarray<int> v0(2, 4);
  valarray<int> v1;
  v1 = v0;
  cout << "v0.size: " << v0.size() << endl;
  cout << "v1.size: " << v1.size() << endl;
  cout << "v0[0]: " << v0[0] << endl;
  cout << "v1[0]: " << v1[0] << endl;
}

Output:

v0.size: 4
v1.size: 0
v0[0]: 2
Segmentation fault

For the assignment:

v1 = v0;

I would think the constructor:

valarray<T>& operator=( const valarray<T>& other );

should be used and according to the documentation, I believe v1 should be resized and the contents of v0 copied into it, element for element. So what's actually happening?

$ g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11)
Tate answered 6/8, 2015 at 22:18 Comment(9)
What platform, compiler, version, standard library implementation etc. are you using? Works just fine here.Psycho
Are you sure that's your output? The text doesn't even match the strings you passed to cout.Barbiturate
@Tate The shown output does not correspond to the code.Roadway
@Praetorian: It must be my implementation or something. I'm on a Centos machine, but my organization uses really old libraries, etc. g++ --version g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11)Tate
Hang on, I'm confused. Someone raised this as a GCC bug once but the conclusion there was that this is standard-conformant. Either that's wrong, or the cppreference.com page is wrong. (Or there was a change somewhere along the way that's not reflected on the cppreference.com page)Schoolteacher
Okay, way to go barking up the wrong tree. I typed it, therefore it's a typo. As @Psycho said, it's apparently an implementation problem with the old crap on our system.Tate
@LightnessRacesinOrbit WTF? So its copy assignment doesn't actually copy assign? valarray is even weirder than I thought it was. Anyway, I'm unfortunate enough to be stuck on the same gcc version at work, and I can reproduce the behavior in the question.Psycho
@LightnessRacesinOrbit: point taken. I can see how this could be a problem. Thanks for feedback.Tate
@LightnessRacesinOrbit Yeah, you managed to dig it up about 30s before I found it in the C++03 std :) +1 for that.Psycho
S
6

Because you're using old C++.

As of C++11, the destination is resized to match the source.
That's why some contributors here could not reproduce your issue (plus, UB has unpredictable results). It's also why the cppreference.com article states that a resize is first performed (though a disclaimer that this applies only since C++11 might have been nice). [This has now been fixed.]

[C++11: 23.6.2.3] valarray assignment [valarray.assign]

valarray<T>& operator=(const valarray<T>& v);

1   Each element of the *this array is assigned the value of the corresponding element of the argument array. If the length of v is not equal to the length of *this, resizes *this to make the two arrays the same length, as if by calling resize(v.size()), before performing the assignment.

2   Postcondition: size() == v.size().

However, in C++03, your code had undefined behaviour.
That's why you're getting a segmentation fault with your older toolchain. It's also why, when this issue was raised as a GCC bug back in 2003, it was rejected as invalid because the implementation was actually conformant at that time.

[C++03: 23.3.2.2] valarray assignment [valarray.assign]

valarray<T>& operator=(const valarray<T>& v);

1   Each element of the *this array is assigned the value of the corresponding element of the argument array. The resulting behavior is undefined if the length of the argument array is not equal to the length of the *this array.

Schoolteacher answered 6/8, 2015 at 22:48 Comment(7)
Wish I could ping @Cubbi; he added that text. I don't know the best way of formatting a clarification in the article.Schoolteacher
I edited it. Think that's the correct format, because it matches that of the range constructor description here. (so you should edit your answer now)Psycho
Changed the style, now it looks like the inline revision difference shown herePsycho
I have code that uses valarray and I'm using gnu++98 and c++03 all the time. I wish I could buy you a beer.Burra
@Psycho / LRiO good to see cppreference fixed without assistance!Hanahanae
@Hanahanae This might need one of your new DR templates instead, though :)Cranford
@Praetorian: Thanks - that inline block stuff is what I had in mind. :) (And I'll know for next time)Schoolteacher

© 2022 - 2024 — McMap. All rights reserved.