Сбой инициализации вектора члена класса с размером - PullRequest
0 голосов
/ 08 февраля 2019

Я новичок в c ++ и столкнулся с этой проблемой.Вот мой код:

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

Это дает мне ошибку, говоря expected a type specifier.Я знаю, что этот способ инициализации вектора неприемлем, и это должно быть сделано в конструкторе, но мне любопытно, почему это не удается.Я также заметил, что это:

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

Работает отлично), а почему первый случай терпит неудачу?спасибо.

PS Я пытаюсь создать вектор размером 10 дюймов, а не вектор с уже вставленным 10.

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Это не очень хорошо написано.Вы также можете использовать следующий пример.Здесь я оставлю вектор пустым, но reserve() пробел для 20 указателей, так что вы можете вставлять без перераспределения.Более простое и лучшее решение (с конструктором) было бы:

A.cpp

#include "A.hpp"

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

A.hpp

#ifndef A_HPP
#define A_HPP_

#include <iostream>
#include <vector>

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

#endif /* !A_HPP_ */

main.cpp

#include "A.hpp"

int main()
{
   A a;
}

Вывод:

Setting size

И ваш векторный размер готов.

0 голосов
/ 08 февраля 2019

Вы не можете объявлять и инициализировать переменную-член с синтаксисом 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 представляет собой объявление члена с составленным списком-объявителем члена .одного элемента, инициализированного инициализатором скобок или равно в форме = initializer-clause.

Аналогично, C::b использует форму braced-init-list .

С другой стороны, вы не найдете синтаксиса для int c(0);.

0 голосов
/ 08 февраля 2019

Что?

Начиная с C ++ 11 у нас есть инициализаторы нестатических элементов данных , что делает этот подход к инициализации элементов полностью допустимым. Однако, вы должны использовать либо =, либо {}.

Формально, если здесь присутствует инициализатор, это должно быть с грамматической продукцией .

Поскольку вместо этого вы использовали синтаксис, который не считается какПри инициализации здесь компилятор пытается сделать объявление функции из vec, что прерывается, потому что 20 не является типом.


Почему?

Глава под названием «Проблема»1 "в первоначальном предложении о функции ( N2756 ) объясняет, что здесь () было запрещено, чтобы избежать некоторой путаницы в отношении объявлений функций-членов.

Автор отмечает, что комитет мог бы позволить этому быть и работать как другие объявления - то есть, если это возможно, это функция, а в противном случае - объект *.Но автор решил пойти в другом направлении и просто запретить синтаксис, чтобы избежать проблемы в данном конкретном случае.

К сожалению, это делает инициализаторы «( expression-list)) ”неоднозначно во время анализа объявления [..]

Одно из возможных решений - полагаться на существующее правило, которое:если объявление может быть объектом или функцией, то это функция [..]

Аналогичным решением будет применение другого существующего правила, которое в настоящее время используется только в шаблонах.что если T может быть типом или чем-то еще, то это что-то еще;и мы можем использовать «typename», если мы действительно имеем в виду тип [..]

Оба этих решения содержат тонкости, которые, вероятно, будут неправильно поняты многими пользователями (о чем свидетельствует множество вопросов на comp.lang.c ++ о том, почему «int i();» в области видимости блока не объявляет инициализированный по умолчанию int).

Предлагаемое решениев этой статье разрешено только инициализировать формы «= initializer-clause » и «{ initializer-list }». Это решает проблему неоднозначности в большинстве случаев.

Такова жизнь.


Итак?

Я пытаюсь создать вектор размером 10 дюймов, а не векторс 10 уже вставленным в него.

Это важный момент.Будьте осторожны, потому что инициализация вектора с {} не сделает это .К сожалению, «единообразная» инициализация просто добавила больше значений .Так много для решения проблемы неоднозначности ...

Поэтому вы должны использовать либо синтаксис =, либо просто сделать это в конструкторе (мой любимый).


*Вот где самый неприятный синтаксический анализ может иногда кусать вас, хотя не каждое появление непреднамеренных объявлений функций является примером самого неприятного синтаксического анализа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...