【问题标题】:Initializing an array of pointers to structs in C++在 C++ 中初始化指向结构的指针数组
【发布时间】:2018-03-01 14:47:19
【问题描述】:

可以使用复合文字来初始化 C 中指向结构的指针数组。

typedef struct {
int a;
int b;
} s;

在 C 中:

s *ptrArray[] = {
    &(s){
        .a = 1,
        .b = 2
    },
    &(s){
        .a = 4,
        .b = 5
    }
};

如何在 C++ 中做到这一点?

我还看到了不使用复合语句在 C++ 中初始化结构的区别:

s s1 = { a: 7, b: 8 };

【问题讨论】:

  • 阅读containerssmart pointerslist initializationaggregate initialization。 C 和 C++ 是两种完全不同的语言。
  • 为什么要使用指针?为什么不想使用std::vector<s> s1 = {{1,2}, {4,5}};
  • 最好避免使用 C++ 中的数组、指针和指针数组。
  • @n.m.:这需要一些链接作为参考或解释。
  • @n.m.:我认为您应该对新手问题的 cmets 采用更具教学性的方法。

标签: c++ arrays pointers struct designated-initializer


【解决方案1】:

首先 - 将任何东西初始化为临时值的地址似乎非常可疑,在 C 中也是如此。你确定这是有效的吗?嗯。无论如何,C++ 编译器真的不会让你这样做。

至于您指定的(命名字段)初始化 C++ 行 - 它实际上是非标准的,它是 GNU C++ 扩展,您不能依赖它。

你可以这样做:

struct s { int a, b; };

int main() {
    s data[] = { { 1, 2 }, { 4, 5 } };
    // instead of ptrArray[i], use &(data[i])
}   

这编译得很好。但是 - 此代码的更多 C++ 版本将是:

#include <array>

struct s { int a, b; };

int main() {
    std::array<s, 2> data { s{ 1, 2 }, s{ 4, 5 } };
    // instead of ptrArray[i], use &(data[i]),
    // or use iterators, or ranged for loops
}   

为什么要使用std::arrayHere's one explanation 的好处。实际上,你可以做得更好,少重复自己:

int main() {
    auto data = make_array(s{ 1, 2 }, s{ 4, 5 });
    // instead of ptrArray[i], use &(data[i]),
    // or use iterators, or ranged for loops
}   

make_array函数取自here;你也有std::experimental::make_array(),但这还没有标准化。

如果您想在运行时从data 添加或删除元素,您可以切换到使用std::vector

#include <vector>

struct s { int a, b; };

int main() {
    std::vector<s> data { s{ 1, 2 }, s{ 4, 5 } };
    // instead of ptrArray[i], use &(data[i]),
    // or use iterators, or ranged for loops
}   

【讨论】:

  • C 中的复合文字具有周围块的生命周期,就好像它们是局部变量一样。它们没有 C++ 临时对象的生命周期。虽然值得注意的是,添加复合文字的 GNU C++ 扩展使用 C++ 临时生命周期。
  • @einpoklum 是的,很抱歉造成混乱。
  • @CandyGumdrop:但是复合字面量是 ptrArray 的初始值设定项,还是指针的初始值设定项也拥有整个程序的生命周期?
  • @einpoklum 每个(type) { initializer }(C99 复合文字)表达式都有效地创建了一个新的匿名局部变量(或全局变量,如果在文件范围内创建),因此使用像int *x = &amp;(int) {123}; 这样的地址是完美的安全,相当于int foo = 123; int *x = &amp;foo;。 OP 的例子相当于用一些局部变量的地址初始化一个数组,这可能是一个完全有效的事情。
【解决方案2】:

您的初始化失败的原因是您试图将指向 struct 的指针数组初始化为数字文字常量的地址。同:

#define A 5
int b = &A;    /* NOT HAPPENING */

(不能取5的地址)

您可以通过简单地初始化 s 数组而不是 指针数组s 来解决您的问题,例如:

    s ptrarr[] = { {1, 2}, {4, 5} };

通过该更改,您的数组将正常初始化,例如

#include <iostream>

typedef struct {
    int a;
    int b;
} s;

int main (void) {

    s ptrarr[] = { {1, 2}, {4, 5} };
    int cnt = 0;

    for (auto& i : ptrarr)
        std::cout << "ptrarr[" << cnt++ << "] : " << i.a << ", " << i.b << "\n";

}

使用/输出示例

$ ./bin/ptrarrystruct
ptrarr[0] : 1, 2
ptrarr[1] : 4, 5

【讨论】:

  • OP 在哪里获取数字文字常量的地址? C99 复合文字评估为具有封闭范围生命周期的左值。 OP 的示例是完全有效的 C,只是使用了 C++ 中不存在的语言功能。
  • 数字初始化器不是复合文字(省略了强制转换)。如果没有强制转换,您将尝试初始化 { {1,2}, {4,5} } 的地址,您无法在 C 或 C++ 中执行此操作。 "initialization makes pointer from integer without a cast"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 2017-01-19
相关资源
最近更新 更多