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

Non-static Data Member Initializers / Calling constructors of std::vector

本文关键字:构造函数 初始化 调用 静态 vector std 数据成员      更新时间:2023-10-16

代码:

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>

我能用什么破解方法吗

如果你的唯一目标是不必"明确"指定两次类型,你可以使用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%确定,我们应该继续阅读大括号或相等的初始化器的真正含义。

8.5/1初始化程序[dcl.init]

大括号或相等的初始值设定项:=初始值设定项子句支持的init列表初始值设定项子句赋值表达式支持的init列表初始值设定项列表初始值设定项子句。。。选择初始化器列表初始化器子句。。。选择braked init列表:{初始值设定项列表,opt}{}

通过以上braked或equal初始值设定项的规范,我们发现在初始化类主体内的成员时,我们面临两个选项,要么使用=初始值设定子句,要么单独使用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   */
};

braked init list看起来很棒,让我们使用它吧

由于std::vector<...>在其构造函数的一个重载中接受std::initializer_list,因此不能使用支持的init列表来调用带有两个参数(size_type count, const T& value)的构造函数,因为这将被用作向量的内容。

因此,我们不得不使用初始值设定项子句

请参阅前面的破解以获得一个确认但可能不那么明显的解决方案

梦幻般的解决方案

如果你只是不想重复std::vector,怎么样

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

这是不允许的,标准规定(7.1.6.4)[dcl.spec.auto]:

auto类型说明符也可用于在选择语句或迭代语句的条件下声明变量,在新表达式的新类型id类型id中的type说明符seq中,以及大括号或等价初始化器声明静态数据成员,该初始化器出现在类定义成员规范中。

大括号或等号初始值设定项语法添加到非静态成员时,他们可能忘记更新此行。