用大小初始化类成员向量失败

时间:2019-02-08 10:51:44

标签: c++ visual-studio class vector

我是c ++的新手,遇到了这个问题。这是我的代码:

class A
{
    std::vector <int> vec(10);
};

给我一​​个错误,说expected a type specifier。我知道这种初始化向量的方法是不可接受的,应该在构造函数中完成,但是我很好奇为什么会失败。我还注意到了这一点:

class A
{
    std::vector <int> vec = std::vector<int>(10);
};

工作正常。

所以我的问题是,即使我们仍在创建具有“预定义大小”(std::vector<int>(10))的向量,为什么第二种情况仍然有效,为什么第一种情况会失败?谢谢。

PS 我正在尝试创建大小为10个整数的矢量,而不是创建带有10的矢量。

3 个答案:

答案 0 :(得分:7)

什么?

自C ++ 11起,我们有了non-static data member initialisers,使初始化成员的方法完全有效。 但是,您必须使用={}

形式上,如果此处存在初始化程序,则it must be的语法形式为brace-or-equal-initializer

由于您在这里使用了不算作初始化的语法,因此编译器会尝试从vec进行函数声明,因为20不是类型,所以这会中断。 / p>


为什么?

原始功能建议(N2756)中名为“问题1”的章节解释说,此处()被禁止,以避免对成员函数声明造成混淆。

作者确实在其中指出,委员会可以允许,并且可以像其他声明一样工作—即,如果可以的话,它是一个函数,否则为对象*。但是作者决定朝另一个方向发展,只是禁止使用语法以避免在这种特殊情况下出现问题。

  

不幸的是,这使得在解析声明时“( expression-list )”形式的初始值设定项不明确 [..] < / em>

     

一种可能的解决方案是依靠现有规则,即如果声明可以是对象或函数,那么它就是函数 [..]      

一种类似的解决方案是应用另一条仅在模板中使用的现有规则,即如果T可以是类型或其他类型,则为其他类型;如果确实是类型 [..]

,则可以使用“ typename”      

这两种解决方案都引入了许多用户可能会误解的细微之处(如comp.lang.c ++上有关“为什么int i();”在块范围内出现的许多问题所证明的那样没有声明默认初始化的int)。

     

本文提出的解决方案是仅允许使用“ = initializer-clause ”和“ { initializer-list }”形式的初始化器。 / strong>在大多数情况下都可以解决歧义性问题。

生活就是这样。


所以?

  

我正在尝试创建大小为10个整数的矢量,而不是创建已经插入10个矢量的矢量。

这是重要的一点。小心,因为用{} won't do that初始化向量。不幸的是,“统一”初始化merely added more meanings。解决歧义问题的事就这么多了……

因此,您应该使用=语法,或者只在构造函数中使用(我最喜欢)。


*这是most vexing parse有时会咬你的地方,尽管并非每次意外的函数声明都是最令人头疼的解析例子。

答案 1 :(得分:1)

它写得不好。您也可以使用以下示例。在这里,我将向量保留为空,但是console.log (res)空间可容纳20个指针,因此您可以插入而不必重新分配。 (使用构造函数)更简单,更好的解决方案是:

A.cpp

reserve()

A.hpp

#include "A.hpp"

A::A()
{
   this->vec.reserve(20);
   std::cout << "Setting size" << std::endl;
}
A::~A()
{
}

main.cpp

#ifndef A_HPP
#define A_HPP_

#include <iostream>
#include <vector>

class A {
public:
        A();
        ~A();
        std::vector<int> vec;
};

#endif /* !A_HPP_ */

输出:

#include "A.hpp"

int main()
{
   A a;
}

向量大小完成了。

答案 2 :(得分:0)

不允许使用语法type name(value);声明和初始化成员变量,但可以使用type name{value};type name = value;

这是标准中的语法:

  

[class.mem]/1

member-declaration:
  attribute-specifier-seq(opt) decl-specifier-seq(opt) member-declarator-list(opt);
  [...]
member-declarator-list:
  member-declarator
  member-declarator-list , member-declarator
member-declarator:
  [...]
  declarator brace-or-equal-initializer(opt)
  [...]

  

[dcl.init]/1

brace-or-equal-initializer:
  = initializer-clause
  braced-init-list
braced-init-list:
  { initializer-list , (opt) }
  { designated-initializer-list , (opt) }
  { }

以下内容:

class C
{
    int a = 0;
    int b{0};
}

有效。

C::a的定义是一个成员声明,其中的 member-declarator-list 由单个成员组成,并以括号初始化。形式为= initializer-clause的等号初始化器

类似地,C::b使用 braced-init-list 形式。

另一方面,您找不到int c(0);的语法。