简体   繁体   中英

C++ gives strange error during structure initialization with an array inside

I try to compile very simple code:

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const int as[3] = { 5, 6, 7, };
    const T t {
        as, 2, 3,
    };
    return 0;
}

But it gives me very strange errors:

t.cpp: In function 'int main()':
t.cpp:11:5: error: array must be initialized with a brace-enclosed initializer
     };
     ^

As from what I understand the compiler wants me to initialize everything in one single place. How do I initialize fields separately and then use them during initiliazation the structure later?

Arrays are neither copy-constructible nor copy-assignable. If you have access to C++11 and newer, you could use std::array .

#include <array>

struct T {
    std::array<int, 3> a;
    int b;
    int c;
};

int main() {
    const std::array<int,3> as = { 5, 6, 7, };
    const T t {
        as, 2, 3,
    };
    return 0;
}

Otherwise you will have to roll a loop and copy the elements individually.

C++ arrays are not copy constructible, so compilation will fail. However,

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const T t {
        {5, 6, 7, }, 2, 3,
    };
    return 0;
}

is an alternative, although it does discard the explicit as variable.

Reference: http://en.cppreference.com/w/cpp/concept/CopyConstructible

As from what I understand the compiler wants me to initialize everything in one single place.

This is because array types decay into pointer types and then the compiler tries to assign a pointer to an array type.

How do I initialize fields separately and then use them during initiliazation the structure later?

You can use pointer types in the structure (which I would not advise). Or you can use container classes instead (STL).

You can also do this, but it assumes your T t data is not really const as I remove its constness with const_cast<>()

#include <cstdio>
#include <cstring>
#include <algorithm>

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const int as[3] = { 5, 6, 7, };

    const T t {
        {0}, 2, 3,
    };

    memcpy( reinterpret_cast< void* >( const_cast< int* > ( t.a ) ), 
            reinterpret_cast< const void* >( as ), 
            std::min( sizeof t.a, sizeof as ) );

    printf( "t.a: '%d, %d, %d'\n", t.a[0], t.a[1], t.a[2] );
    return 0;
}

If you data T t is not actually const, you can do it without the const_cast<>()

#include <cstdio>
#include <cstring>
#include <algorithm>

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const int as[3] = { 5, 6, 7, };

    T t {
        {0}, 2, 3,
    };

    memcpy( reinterpret_cast< void* >( t.a ),
            reinterpret_cast< const void* >( as ), 
            std::min( sizeof t.a, sizeof as ) );

    printf( "t.a: '%d, %d, %d'\n", t.a[0], t.a[1], t.a[2] );
    return 0;
}

I am adding the reinterpret_cast<>() because memcpy() requires a void*

function void * memcpy ( void * destination, const void * source, size_t num );

Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination. http://www.cplusplus.com/reference/cstring/memcpy/

I am also doing std::min( sizeof ta, sizeof as ) to avoid override any data it should not in case the source array is way bigger than expected.

And finally, {0} is initializing by default the destine array with zeros. It could also be {} to not initialize anything and let the default values to be trash memory/random data.

References:

  1. When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
  2. Should I use static_cast or reinterpret_cast when casting a void* to whatever
  3. When to use reinterpret_cast?
  4. Should I use a C++ reinterpret_cast over a C-style cast?
  5. Use of min and max functions in C++

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM