2

The following C++ code compiles with no errors or warnings, but for some reason when I print out the contents of foo.arr I just get junk values. It looks like the array member is not being properly initialized.

template<int n> class C{
  public:
  const uint8_t (&arr)[n];
  const int length = n;
  C(const uint8_t (&arr_arg)[n]):arr(arr_arg)
  {}
};

int main() {
    C<5> foo{{1,2,3,4,5}};
    for(int i =0;i<foo.length;i++){      
      printf("foo.arr[%d]=%2x\r\n",i,foo.arr[i]);
    };
}

But if I write it like this, foo.arr is correctly initialized when I print out the results.

int main() {
    const uint8_t x[]{1,2,3,4,5};
    C<5> foo{x};
    for(int i =0;i<foo.length;i++){      
      printf("foo.arr[%d]=%2x\r\n",i,foo.arr[i]);
    };
}

Why does the second case work, but the first one doesn't?

One would think that the compiler would create a block of five bytes for the constant data {1,2,3,4,5} and then the initializer for foo would point foo.arr to that block of bytes. It seems that whatever foo.arr is pointing either not where that data is, or else that data doesn't exist any more by the time I print it out (possibly overwritten).

user4574
  • 310
  • 4
  • 8

1 Answers1

1
C<5> foo{{1,2,3,4,5}};

The constructor's parameter is a reference to a temporary object that gets destroyed after the constructor call finishes. All subsequent reference to this object results in undefined behavior.

C<5> foo{x};

Here, the constructor's parameter is a reference to an object that remains in scope and continues to exist as long as it is subsequently referenced and used.

It seems that ... data doesn't exist any more by the time I print it out (possibly overwritten).

That is, indeed, what's happening.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • 1
    Is there any form of the initializer list syntax that can allow me to initialize my object without an extra copying step and without creating an extra variable? I know such a thing exists in a lot of other languages. – user4574 Jan 22 '23 at 04:55
  • @user4574 you may want to watch Jason Turner's C++Now 2018 talk [Initializer Lists Are Broken, Let's Fix Them](https://www.youtube.com/watch?v=sSlmmZMFsXQ) short answer: no you can't do that with arrays or std::initializer_list, but you can work with a variadic template as a substitute, though not sure it would worth the effort. – Amir Kirsh Jan 22 '23 at 06:23