c ++使用数组作为成员初始化结构

Dre*_*fer 25 c++ portability struct initialization

再次编辑,因为我最初并不清楚我是否正在尝试在编译时初始化数组,而不是在运行时...


我有以下简化的测试用例:

typedef struct TestStruct
{
    int length;
    int values[];
};

TestStruct t = {3, {0, 1, 2}};
TestStruct t2 = {4, {0, 1, 2, 3}};

int main()
{
    return(0);
}
Run Code Online (Sandbox Code Playgroud)

这适用于Visual C++,但不能在linux下用g ++编译.任何人都可以帮助我使这种特定的初始化器可移植吗?

其他细节:我正在使用的实际结构有几个其他int值,并且数组的长度范围可以从单个条目到超过1800个条目.

编辑:我认为(但不确定)这不是VLA问题.为了澄清,我正在尝试让编译器在编译时为我完成工作.运行时数组的长度是不变的.如果我错了,请道歉; 我主要是ac#/ Perl/Ruby程序员,他们坚持维护这个遗留应用程序......

任何帮助非常感谢.谢谢!

Eva*_*ran 29

c ++没有与c99一样的最后一个元素的灵活数组成员.std::vector如果你不知道有多少元素,你应该使用a ,或者你应该指定多少元素.

编辑:你已经在你的编辑中说过,数组是一个运行时常量,所以指定大小,它应该工作正常.g ++使用以下代码没有问题:

struct TestStruct { // note typedef is not needed */
    int length;
    int values[3]; // specified the size
};

TestStruct t = {3, {0, 1, 2}};

int main() {
    // main implicitly returns 0 if none specified
}
Run Code Online (Sandbox Code Playgroud)

编辑:要解决您的评论,您可以使用这样的模板:

template <int N>
struct TestStruct {
    int length;
    int values[N];
};

TestStruct<3> t3 = {3, {0, 1, 2}};
TestStruct<2> t2 = {2, {0, 1}};

int main() {}
Run Code Online (Sandbox Code Playgroud)

唯一的问题是没有简单的方法将t2和t3放在一个容器中(比如list/vector/stack/queue/etc,因为它们有不同的大小.如果你想要,你应该使用std::vector.另外,如果你正在这样做,然后没有必要存储大小(它与类型相关联.)所以你可以这样做:

template <int N>
struct TestStruct {
    static const int length = N;
    int values[N];
};

TestStruct<3> t3 = {{0, 1, 2}};
TestStruct<2> t2 = {{0, 1}};

int main() {}
Run Code Online (Sandbox Code Playgroud)

但是再一次,你不能轻易地将t2和t3放在一个"集合"中.

编辑: 总而言之,它听起来像你(除非你存储的数据多于一些数字和大小)根本不需要结构,并且不能只使用普通的旧向量.

typedef std::vector<int> TestStruct;


int t2_init[] = { 0, 1, 2 };
TestStruct t3(t3_init, t3_init + 3);

int t2_init[] = { 0, 1 };
TestStruct t2(t2_init, t2_init + 2);

int main() {}
Run Code Online (Sandbox Code Playgroud)

这将允许您将t2和t3同时放在一个集合中.不幸的std::vector是(还)没有数组样式的初始化语法,所以我使用了一个快捷方式.但是编写一个函数来以一种很好的方式填充向量很简单.

编辑:好的,所以你不需要一个集合,但你需要将它传递给一个函数,你可以使用模板来保持类型安全!

template <int N>
struct TestStruct {
    static const int length = N;
    int values[N];
};

TestStruct<3> t3 = {{0, 1, 2}};
TestStruct<2> t2 = {{0, 1}};

template <int N>
void func(const TestStruct<N> &ts) { /* you could make it non-const if you need it to modify the ts */
    for(int i = 0; i < N; ++i) { /* we could also use ts.length instead of N here */
        std::cout << ts.values[i] << std::endl;
    }
}

// this will work too...
template <class T>
void func2(const T &ts) { 
    for(int i = 0; i < ts.length; ++i) {
        std::cout << ts.values[i] << std::endl;
    }
}

int main() {
    func(t2);
    func(t3);
    func2(t2);
}
Run Code Online (Sandbox Code Playgroud)

  • 好.现在我只想给你买啤酒. (12认同)

小智 6

GCC/Clang 支持以下扩展

    typedef 结构体 TestStruct
    {
        整数长度;
        int* 值;
    };

    TestStruct t = {3, (int[]){0, 1, 2}};
    TestStruct t2 = {4, (int[]){0, 1, 2, 3}};

  • 这仅适用于静态/全局级别。如果在方法中执行此操作,编译器将生成一个临时的 int 数组,将其分配给结构,然后立即销毁该数组,使结构留下一个错误的指针;如果您尝试这样做,GCC 会发出警告。 (4认同)