【问题标题】:most vexing parse prevents in-class initializing a std::vector<int>最令人头疼的解析会阻止类内初始化 std::vector<int>
【发布时间】:2018-07-21 05:43:04
【问题描述】:

C++11 允许类内初始化:

struct Foo{
    std::vector<std::string> v{3}; // vector of 3 empty strings
};

如果我们想在类内初始化一个 ints 的向量,我们会得到别的东西:

struct Foo{
    std::vector<int> v{3}; // vector of one element with value 3
};

这个问题似乎是语言的限制,as discussed in previous questions。但是,如果这不是类内初始化,我们将能够使用括号而不是大括号,并获得所需的结果:

std::vector<int> v(3); // vector of three zeros

但是,由于most vexing parse,我们不能在课堂上这样做:

struct Foo{
    std::vector<int> v(3); // most vexing parse; doesn't compile
};

当然,上面的代码是否是好的设计实践还有待商榷,因为我们可以很容易地将我们正在尝试做的事情转移到构造函数中。但是暂时把它放在一边,有没有办法执行所需的初始化,尽可能接近第一个 std::string 示例,这没有问题?

【问题讨论】:

  • std::vector&lt;int&gt; v(3); 如何是最令人头疼的解析的示例?我无法理解。顺便说一句,涉及最烦人的解析 确实的代码可以编译;只是它的含义与您的预期不同。
  • 这不是最麻烦的解析。语言根本不允许这样做。
  • @Nawaz: std::vector&lt;int&gt; v(3); 在类定义中不能在 C++11 中编译,如上面的 struct Foo
  • @xdavidliu:我的问题是,最令人头疼的解析是怎样的?你什么时候得到的?
  • @Nawaz 我的印象是 std::vector&lt;int&gt; v(3); 在类声明中不会编译,因为编译器无法判断我们是在尝试声明成员向量 v 还是声明函数名称为v。我的印象是这个问题被称为“最令人烦恼的解析”。您能告诉我其中哪一部分不正确吗?

标签: c++ c++11 constructor initialization most-vexing-parse


【解决方案1】:

默认成员初始值设定项也适用于 =。所以

struct Foo{
    std::vector<int> v = std::vector<int>(3);
};

会做的。虽然很明显,一个主要的警告是我们在这里重复了类型名称。

我们可以通过decltype 缓解它:

struct Foo{
    std::vector<int> v = decltype(v)(3);
};

但这仍然需要我们两次命名。

【讨论】:

  • 嗯,我想知道为什么 auto 不允许用于具有类内初始化程序的成员...这会使其更具可读性。
  • @RemyLebeau - OP 提到它是他们将采用的明显解决方案。这篇文章的重点是是否可以使用默认成员初始化器。
  • @Swift - 什么是不可能的?我不明白你在说什么
  • OP 清楚地询问如何使用 std::vector 的所需 c'tor,因为默认成员初始化程序不接受圆括号 ()。说这是不可能的并且没有解决方法,因为我很清楚地提出了一个问题,这是一件很奇怪的事情。
  • @Swift - 你和我对“关闭”的解释不同。我认为它的意思是最后调用了相同的 c'tor(为了调味而省略了一些复制)。不强迫特定的初始化程序像它不能那样工作不是我从 OP 中理解的。
猜你喜欢
  • 2020-08-17
  • 2013-06-08
  • 1970-01-01
  • 2018-05-26
  • 2019-11-30
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
相关资源
最近更新 更多