在结构初始化期间,C ++在

时间:2017-09-14 06:51:33

标签: c++

我尝试编译非常简单的代码:

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;
}

但它给了我很奇怪的错误:

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

根据我的理解,编译器希望我在一个地方初始化所有内容。如何分别初始化字段,然后在初始化结构时使用它们?

4 个答案:

答案 0 :(得分:21)

数组既不是可复制构造的,也不是可复制的。如果您可以访问C ++ 11及更高版本,则可以使用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;
}

否则,您必须滚动循环并单独复制元素。

答案 1 :(得分:10)

C ++数组不是可复制构造的,因此编译将失败。然而,

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

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

是一种替代方法,但它确实丢弃了显式的as变量。

参考:http://en.cppreference.com/w/cpp/concept/CopyConstructible

答案 2 :(得分:1)

  

根据我的理解,编译器希望我在一个地方初始化所有内容。

这是因为数组类型衰减为指针类型,然后编译器尝试分配指向数组类型的指针。

  

如何单独初始化字段,然后在初始化结构时使用它们?

您可以在结构中使用指针类型(我不建议)。或者您可以使用容器类(STL)。

答案 3 :(得分:0)

您也可以这样做,但是它假定您的T t数据不是真正的常量,因为我使用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;
}

如果您的数据T t实际上不是const,则可以不用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;
}

我要添加reinterpret_cast<>()是因为memcpy()需要void*

  

功能   void * memcpy(void *目标,const void *源,size_t num);

     

将num字节的值从源指向的位置直接复制到目标指向的存储块。   http://www.cplusplus.com/reference/cstring/memcpy/

我也在做std::min( sizeof t.a, sizeof as )以避免覆盖源数组超出预期的情况下不应该覆盖的任何数据。

最后,{0}默认用零初始化目标数组。也可能{}不进行任何初始化,而将默认值设置为垃圾存储/随机数据。

参考文献:

  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++