【问题标题】:Initializing a pointer to structure with a constant array用常量数组初始化指向结构的指针
【发布时间】:2021-10-27 11:37:33
【问题描述】:

假设我有两个结构

struct A
{ int x;
  int y;
};

struct B
{ int count;
  const A* list;
};

现在我要初始化一个编译时间常数Bs。

static const B Barray[] =
{ { 2,
    { { 7,8 }, {9,10} } // error
  },
  { 1,
    { { 30,40 } } // error
  },
};

后者(当然)不起作用,因为list 未声明为数组。但这是(旧)API 经常声明的方式。

我可以使用一个基本上只是演员表的辅助函数:

template<typename T>
constexpr static const T* make_pointer(const T (&array)[])
{
    return array;
}

static const B Barray[] =
{ { 2,
    make_pointer<A>({ { 7,8 }, {9,10} })
  },
  { 1,
    make_pointer<A>({ { 30,40 } })
  }
};

但这不是那么漂亮。 是否可以在没有辅助函数的情况下直接初始化数据结构? (当然,每个 A[] 都没有命名静态常量。)

【问题讨论】:

  • 您需要在编译时使用它吗?如果没有,const std::vector&lt;A&gt; 会为您工作。它让你有一个运行时确定的大小,但你不能在构造后改变那个大小,你只能改变向量中的元素。如果你不想这样,你甚至可以使用const vector&lt;const A&gt;。
  • vector&lt;&gt; 不会有任何帮助,因为它还需要一些绑定到的静态存储。否则只是暂时的。所以vector 对每个数组的命名静态常量没有任何优势。

标签: c++ arrays initialization


【解决方案1】:

但这不是那么漂亮。

这不仅不漂亮,而且几乎没用,因为临时数组的生命周期在静态数组初始化后立即结束,指针悬空。

这可行,但远非漂亮:

static const B Barray[] =
{ { 2,
    []{static A a[] { { 7,8 }, {9,10} }; return a; }(),
  },
  { 1,
    []{static A a[] { { 30,40 } }; return a; }(),
  },
};

命名静态数组可能是目前最好的选择


不管怎样,C99 及更高版本中有一个语言特性:复合文字。流行的编译器也将其作为 C++ 中的语言扩展来实现,但它们的实现存在一些变化,而且至关重要的是,例如 GCC 复合文字在 C++ 中是临时的而不是静态的,因此不适用于此用例。

有一个proposal 需要标准化,因此它可能是未来 C++ 标准中的一个选项。编辑:我认为正如提议的那样,C++ 中的复合文字不会有静态存储,如果这种解释是正确的,那么它将不适用于这个用例。

【讨论】:

  • 快速提问:如果make_pointer 函数标记为static,问题中的示例是否有效?
  • @Apple_Banana make_pointer 在问题中标记为 static。它对传递给函数的临时参数没有影响。
  • 好吧,没关系。我知道我没有问这个问题,但我很感兴趣,但我不明白这个[]{static A a[] { { 7,8 }, {9,10} }; return a; }()
  • 我特别不明白这一点static A a[] ,因为我还没有看到像这样声明lamdas
  • @Apple_Banana static A a[] 不是 lambda。它是 lambda 内部的一个局部变量。您在之前评论中引用的表达式有时称为“立即调用函数表达式”。
猜你喜欢
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多