非静态数据成员初始化器/调用std :: vector的构造函数

时间:2012-07-11 17:40:48

标签: c++ c++11

代码:

class A {
  std::vector<int> x = {2,3};                 // x[0] = 2 and x[1] = 3
  std::vector<int> y = std::vector<int>(2,3); // x[0] = 3 and x[1] = 3 Too verbose!!  
};

有没有办法可以只使用大括号初始化程序来调用std::vector<int>的构造函数,或者至少是更短的版本,它会产生相同的效果?

我不想重复std::vector<int>

2 个答案:

答案 0 :(得分:6)

我可以使用任何黑客吗?

如果您的唯一目标是不必“明确”指定两次类型,则可以使用decltype为您的任务提供一些帮助:

class Obj {
  std::vector<int> v1 = decltype(v1) (2,3);
};

还要记住,typedef / using是一种无需输入 1 的好方法:

struct Obj {
   using VInt = std::vector<int>;
// typedef std::vector<int> VInt;

   VInt v = VInt (3,2);
};

1。 双关语


标准对此有何评价?

遗憾的是,该标准规定了以下关于在班级正文中初始化成员的内容:

  

9.2 / 5班级成员[class.mem]

     

可以使用大括号或等于初始化程序初始化成员。 (对于   静态数据成员,见9.4.2;对于非静态数据成员,请参阅   12.6.2)。

我们已经在初始化成员时发现了一些关于什么是什么和什么不可行的提示,但要100%确定我们应该继续阅读 brace-or-equal-initializer < / em>真的是。

8.5/1 Initializers [dcl.init]

... brace-or-equal-initializer: = initializer-clause braced-init-list initializer-clause: assignment-expression braced-init-list initializer-list: initializer-clause ...opt initializer-list , initializer-clause ...opt braced-init-list: { initializer-list ,opt } { }

使用 braced-or-equal-initializer 的上述规范,我们发现在使用=一起初始化类的主体内的成员时,我们面临两个选项使用初始化子句或自己的braced-init-list

以上归结为这两者中的任何一个:

struct Obj {
  Type foo = Type (1,2,3); /* example of an initializer-clause */
  Type bar        {1,2,3}; /* example of a  braced-init-list   */
};

braced-init-list 看起来很棒,让我们使用它!

由于std::vector<...>在其构造函数的一个重载中接受std::initializer_list,我们无法使用 braced-init-list 来调用构造函数两个参数(size_type count, const T& value),因为它将被用作 vector 的内容。

因此我们坚持使用 initializer-clause

请参阅前面的 hack 以获得确认,但可能不是那么明显的解决方案。

答案 1 :(得分:-2)

梦幻般的解决方案..

如果您不想重复std::vector,那么

怎么样?
class A
{
    auto y = std::vector<int>(2,3);
};

不允许 ,标准说(7.1.6.4)[dcl.spec.auto]

  

{em> type-specifier-seq <在 type-specifier-seq <中,可以使用auto类型说明符在选择语句或迭代语句的条件中声明变量/ em>在新表达式的 new-type-id type-id 中,在 for-range-declaration 中, 声明一个静态数据成员,其中包含成员规范大括号

brace-or-equal-initializer 语法被添加到非静态成员时,他们可能忘记更新此行。