vector<T>
имеет конструктор, который принимает размер вектора, и, насколько я знаю, это явный, что может быть доказано тем фактом, что следующий код не компилируется
void f(std::vector<int> v);
int main()
{
f(5);
}
Я не могу понять и прошу вас объяснить, почему следующий код компилируется
std::vector<std::vector<int>> graph(5, 5);
Он не только компилируется, он фактически изменяет размер графика до 5 и устанавливает для каждого элемента вектор из пяти нулей, то есть делает то же самое, что и код, который я обычно пишу:
std::vector<std::vector<int>> graph(5, std::vector<int>(5));
Как? Зачем?
Компилятор: MSVC10.0
ОК, похоже, это ошибка MSVC (еще одна). Если кто-то может уточнить ошибку в ответе (то есть обобщить случаи, когда она воспроизводится), я бы с радостью принял ее
Это не совсем ошибка. Вопрос в том, что может пойти не так, чтобы разрешить второй кусок кода, пока первый не компилируется?
Проблема в том, что, хотя вам кажется очевидным, какой конструктор вы хотите вызвать, когда вы это делаете:
std::vector<std::vector<int>> graph(5, 5);
это не очень понятно для компилятора. В частности, есть две перегрузки конструктора, которые могут потенциально принимать аргументы:
vector(size_type,const T& value = T());
template <typename InputIterator>
vector(InputIterator first, InputIterator last);
Первый требует преобразования 5
в size_type
(без знака), в то время как второй — идеальное совпадение, так что это будет тот, который подобрал компилятор …
… но компилятор требует, чтобы вторая перегрузка, если выведенный тип InputIterator
Интеграл ведет себя так, как если бы это был вызов:
vector(static_cast<size_type>(first),static_cast<T>(last))
Что стандарт C ++ 03 эффективно предписывает, так это то, что второй аргумент эксплицитно конвертируется из оригинального типа int
к типу назначения std::vector<int>
, Поскольку преобразование явное, вы получаете ошибку.
Стандарт C ++ 11 изменяет формулировку, чтобы использовать SFINAE для отключения конструктора итератора, если аргумент на самом деле не является входным итератором, поэтому в компиляторе C ++ 11 код должен быть отклонен (что, вероятно, является причиной, по которой некоторые утверждают, что это быть ошибкой).
Мне кажется, это вызывает этот конструктор:
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
Я не уверен где explicit
входит в это, потому что конструктор принимает несколько параметров. Это не автоматическое приведение от int к вектору.
На самом деле это расширение, а не ошибка.
Вызываемый конструктор — это тот, который принимает два итератора (но на самом деле сигнатура будет соответствовать любым двум параметрам одного типа); Затем он вызывает специализацию, когда два итератора на самом деле int
, который явно создает value_type
используя значение end
и заполняет вектор begin
копии этого.
станд :: вектор< int> имеет конструктор, который принимает size_type и const int&, Это тот конструктор, который я бы ожидал вызвать в этом случае, инициализируя вектор 5-ю целыми числами, каждое со значением 5.