1

I have a class called Array2D with a copy-constructor Array2D(const Array2D&). I had the problem that my program would stop whenever the copy-constructor was called. The constructor was:

Array2D(const Array2D& arr) {
    Array2D(arr.rows, arr.cols); //Sets the variables cols and rows and
                                 //sets a pointer T* ptr = new T[rows*cols]
    for(size_t i = 0; i < rows*cols; i++)
        ptr[i] = arr.ptr[i];
}

I moved the call for the other constructor to the contructor list:

Array2D(const Array2D& arr)
: Array2D(arr.rows, arr.cols) {
    for(size_t i = 0; i < rows*cols; i++)
        ptr[i] = arr.ptr[i];
}

Could anyone tell me why the second version of the code works and the second one doesn't?

P.S.: This is the constructor that is called from the copy constructor.

Array2D(size_t r, size_t c)
: rows(r), cols(c), ptr(new T[r*c]) {}
  • related: http://stackoverflow.com/questions/308276/call-constructor-from-constructor-in-c – default Mar 10 '16 at 19:19
  • I'll let you answer your own question by asking you: what if in the first code, I wanted to create another Array2D inside of the constructor, completely separate and apart from `*this`? How would I do that? Ahh..do you see now what the first code is actually doing? – PaulMcKenzie Mar 10 '16 at 19:19
  • Looks like somebody is moving away from Java :) – SergeyA Mar 10 '16 at 19:27
  • @SergeyA You are right. –  Mar 10 '16 at 19:28

1 Answers1

4

In

Array2D(const Array2D& arr) {
    Array2D(arr.rows, arr.cols); //Sets the variables cols and rows and
                                 //sets a pointer T* ptr = new T[rows*cols]
    for(size_t i = 0; i < rows*cols; i++)
        ptr[i] = arr.ptr[i];
}

Array2D(arr.rows, arr.cols); is basically a non-op. It creates a temporary Array2d and then it gets destroyed. This means ptr is never initialized and using it is undefined behavior.

With

Array2D(const Array2D& arr)
: Array2D(arr.rows, arr.cols) {
    for(size_t i = 0; i < rows*cols; i++)
        ptr[i] = arr.ptr[i];
}

You use a delegating constructor to initialize the member variables and then you set the array elements.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • I didn't know that you could create an object without assigning it a name. Thank you! –  Mar 10 '16 at 19:24
  • @N.Pich It is perfectly legal. It is one of the the ways you use `auto` like: `auto data = std::vector(some_size);`. Here we create a temporary vector and then it is with copied/moved/elided into `data`. – NathanOliver Mar 10 '16 at 19:27
  • @N.Pich What would you have thought happened if say, you moved that `Array2D(arr.rows, arr.cols)` after the `for` loop? That would have been legal also. Doing that would have caused some suspicion that the line in question was not really being used to construct your current object. – PaulMcKenzie Mar 10 '16 at 19:31