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)
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Bryant
  • 334
  • 1
  • 11
  • 4
    What platform, compiler, version, standard library implementation etc. are you using? Works just fine [here](http://coliru.stacked-crooked.com/a/dc1620e9787f0d13). – Praetorian Aug 06 '15 at 22:21
  • 1
    Are you sure that's your output? The text doesn't even match the strings you passed to `cout`. – Benjamin Lindley Aug 06 '15 at 22:28
  • 1
    @Bryant The shown output does not correspond to the code. – Vlad from Moscow Aug 06 '15 at 22:33
  • @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) – Bryant Aug 06 '15 at 22:35
  • Hang on, I'm confused. Someone raised this as [a GCC bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11126) 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) – Lightness Races in Orbit Aug 06 '15 at 22:42
  • Okay, way to go barking up the wrong tree. I typed it, therefore it's a typo. As @Praetorian said, it's apparently an implementation problem with the old crap on our system. – Bryant Aug 06 '15 at 22:42
  • @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. – Praetorian Aug 06 '15 at 22:45
  • @LightnessRacesinOrbit: point taken. I can see how this could be a problem. Thanks for feedback. – Bryant Aug 06 '15 at 22:48
  • @LightnessRacesinOrbit Yeah, you managed to dig it up about 30s before I found it in the C++03 std :) +1 for that. – Praetorian Aug 06 '15 at 23:17

1 Answers1

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.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Wish I could ping [@Cubbi](https://stackoverflow.com/users/273767/cubbi); [he added that text](http://en.cppreference.com/mwiki/index.php?title=cpp/numeric/valarray/operator%3D&diff=prev&oldid=68852). [I don't know](http://en.cppreference.com/w/Talk:cpp/numeric/valarray/operator%3D) the best way of formatting a clarification in the article. – Lightness Races in Orbit Aug 06 '15 at 22:59
  • I edited it. Think that's the correct format, because it matches that of the range constructor description [here](http://en.cppreference.com/w/cpp/container/vector/vector). (so you should edit your answer now) – Praetorian Aug 06 '15 at 23:16
  • Changed the style, now it looks like the inline revision difference shown [here](http://en.cppreference.com/w/cpp/language/default_constructor#Deleted_implicitly-declared_default_constructor) – Praetorian Aug 06 '15 at 23:27
  • 1
    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. – user3528438 Aug 07 '15 at 00:00
  • @Praetorian / LRiO good to see cppreference fixed without assistance! – Cubbi Aug 07 '15 at 01:18
  • @Cubbi This might need one of your new DR templates instead, though :) – T.C. Aug 07 '15 at 01:22
  • @Praetorian: Thanks - that inline block stuff is what I had in mind. :) (And I'll know for next time) – Lightness Races in Orbit Aug 07 '15 at 10:07