【问题标题】:Initialising boost::array after declaration声明后初始化 boost::array
【发布时间】:2014-04-20 15:34:59
【问题描述】:

我们可以使用以下语法初始化 boost 或 std::array:

array<int,5> b = {1, 2, 3, 4, 5};

如果 'b' 是局部变量,这很好。如果'b'是班级成员呢?

b = {1, 2, 3, 4, 5}; // Error: expected an expression
b = array<int,5>{1, 2, 3, 4, 5}; // Error: type name is not allowed 
b = array<int,5>({1, 2, 3, 4, 5}); // Error: expected an expression
b = array<int,5>(1, 2, 3, 4, 5); // Error: no suitable constructor exists to convert from "int" to "array<int, 5>"

你真的必须这样做吗:

array<int,5> c = {1, 2, 3, 4, 5};

b = c;

这似乎有点浪费,因为它创建'c',初始化它,然后在销毁'c'之前将其复制到b中。

【问题讨论】:

  • 说明编译器的版本。
  • 我认为编译器的版本不会有帮助,但它支持 C++ 2003 标准。
  • 所以你使用c++03(与c++0x不同)?
  • 也许我不知道 c++0x 到底是什么,但是是的,它是 2003 年。所有这些不同的版本让我感到困惑。
  • c++0x 是 C++11 获得批准之前“下一个标准”的占位符。对正在开发的未来标准的最佳解释的不完整实施也是如此。所以编译器版本确实很重要,因为版本越大,越接近 C++11。

标签: c++ arrays boost c++03


【解决方案1】:

您还可以在声明时初始化数据成员:

struct Foo
{
  array<int,5> b = {1, 2, 3, 4, 5};
};

或者,你也可以使用构造函数初始化列表

struct Foo
{
  Foo() : b{1, 2, 3, 4, 5} {}
  array<int,5> b;
};

注意,您所有涉及b = X 的语句都不是初始化,它们是赋值

编辑: 这种初始化在 C++03 中是不可能的,但是您可以通过调用返回合适的初始化数组的函数来实现类似的功能:

boost::array<int, 5> make_array()
{
  // trivial example, but you can do more complicated stuff here
  boost::array<int, 5> a = {{1, 2, 3, 4, 5}};
  return a;
}

然后

Foo() : b(make_array()) {}

【讨论】:

  • 对不起,变量在类中并且编译器不支持数据初始化,所以我必须在构造函数中进行初始化。我猜他们是任务,是的。
  • @Steve 变量也在此处的类中。无论如何,以上是有效的 C++11。如果你不能使用 C++11,你应该在问题中明确说明。
  • 我明确表示“我没有使用 C++11”。我现在删除了它并添加了标签“C++03”。
  • @Steve 好吧,你设法让两个人给你 C++11 答案,所以显然标签和/或问题有些混乱。
  • 确实如此。那么你是说这在 C++03 中是不可能的吗?如果没有,将其添加到您的问题中将使其被接受:)
【解决方案2】:

您可以像在您的问题中那样创建它们,这将在堆栈上创建一个临时对象,然后将其复制到您的实例(这可能有点浪费),或者您可以使用静态变量和任何编译器的初始化列表物有所值只会初始化类的适当成员:

class temp
{
   public:
   temp():b(b_default) {}
   array<int, 5> b;
   static array<int, 5> b_default;
};
array<int, 5> temp::b_default = {1,2,3,4,5};

然而,这种方式可能是“最干净”的方式:(同样,所有体面的编译器都只有一个副本)

class temp
{
   public:
   temp() 
   {
    static const array<int, 5> b_default = {1,2,3,4,5};

    b = b_default;
   }
   array<int, 5> b;
   static const array<int, 5> b_default;
};

【讨论】:

  • 您仍在初始化 然后 分配给数据成员。没必要这么做。
  • 它会生成与您的答案完全相同的代码,但不必为我需要初始化的每个数组都有一个方法(只是一个被优化的额外变量),所以我会这么说是这里最干净的方式。如果您有更好的方法,请发布。
【解决方案3】:

您可以使用以下内容:

struct S
{
  std::array<int, 5> b = {{1, 2, 3, 4, 5}};
};

注意双重{

【讨论】:

  • 不应需要双括号。大括号省略应该允许单个大括号。
  • 错误:不允许数据初始化。
  • @juanchopanza: gcc 4.8.1 需要它:ideone.com/vAv4Fh ... 而我收到了关于 clang 3.4 的警告
  • @Jarod42 我认为要求它是错误的。但这是 C++11 标准的一个不清楚的方面,可能已针对 C++14 进行了修复。
【解决方案4】:

就个人而言,我通过创建自己的初始化函数来解决此类问题。在这里,使用预处理器(为了与 C++03 保持兼容),但可以使用可变参数模板 (>= c++11) 来完成。

#define NMAX_MAKE_ARRAY_PARAMETERS 30
#define MAKE_ARRAY_EDIT(z, n, data) \
  a__[n] = x__ ## n;
#define MAKE_ARRAY_DEFINITION(z, n, data) \
  template <typename T> boost::array<T,n> make_array(BOOST_PP_ENUM_PARAMS(n, const T& x__)) \
  { \
    boost::array<T,n> a__; \
    BOOST_PP_REPEAT(n, MAKE_ARRAY_EDIT, 0) \
    return a__; \
  }
#define MAKE_ARRAY_DEFINITIONS(n) \
  BOOST_PP_REPEAT(BOOST_PP_INC(n), MAKE_ARRAY_DEFINITION, 0)
MAKE_ARRAY_DEFINITIONS(NMAX_MAKE_ARRAY_PARAMETERS)

包含此代码后,我可以轻松创建大小在 0 到 30 之间的数组:

boost::array<double,5> a = make_array<double>(1.0, 2.2, 3.4, 4.6, 5.8);
a = make_array<double>(0.0, 0.1, 0.2, 0.3, 0.4);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 2011-04-15
    • 2018-08-13
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多