为什么我不能通过传递临时输入迭代器来构造向量?
Why can't i construct a vector by passing temporary input iterator?
我经常使用 istream_iterator 将标准输入复制到向量中,如下所示:
copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(vec));
有效。
今天当我用这个构造向量时:
vector<int> vec(istream_iterator<int>(cin), istream_iterator<int>());
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
就是编译不了!
但是如果我这样构建它:
istream_iterator<int> beg(cin), end;
vector<int> vec(beg, end);
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
有效。
为什么?我不能使用临时变量来构造向量吗?如果可以,但为什么我使用 std::copy 时可以这样做?
ps:我是在vs2005下编译的,使用了如下头文件:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
不幸的是,这是一个函数声明:
vector<int> vec(istream_iterator<int>(cin), istream_iterator<int>());
这是一个名为 vec
的函数,returns 一个 vector<int>
的值,它有两个参数:一个 istream_iterator<int>
,形式参数名称为 cin
,以及一个没有形式参数名称的函数 returns 和 istream_iterator<int>
,并且不带任何参数。
为什么?
基本上,在 C++(和 C)中,如果一段代码可以解释为声明,那么它就是。
根据N3936::6.8.1 [stmt.ambig]:
There is an ambiguity in the grammar involving expression-statements
and declarations: An expressionstatement with a function-style
explicit type conversion (5.2.3) as its leftmost subexpression can be
indistinguishable from a declaration where the first declarator starts
with a (. In those cases the statement is a declaration. [ Note: To
disambiguate, the whole statement might have to be examined to
determine if it is an expression-statement or a declaration. This
disambiguates many examples. [ Example: assuming T is a
simple-type-specifier (7.1.6),
T(a)->m = 7; // expression-statement
T(a)++; // expression-statement
T(a,5) << c; // expression-statement
T(*d)(int); // declaration
T(e)[5]; // declaration
T(f) = { 1, 2 }; //declaration
T(*g)(double(3)); // declaration
In the last example
above, g, which is a pointer to T, is initialized to double(3). This
is of course ill-formed for semantic reasons, but that does not affect
the syntactic analysis. —end example ]
如何修复
我们所需要的只是使编译器无法将代码视为函数声明的东西。
在参数周围添加额外的括号可以清楚
编译器认为我们打算成为构造函数参数名称不能是参数声明。
vector<int> vec((istream_iterator<int>(cin)), istream_iterator<int>());
如您的解决方案所示,使用命名变量作为构造函数参数。
我经常使用 istream_iterator 将标准输入复制到向量中,如下所示:
copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(vec));
有效。
今天当我用这个构造向量时:
vector<int> vec(istream_iterator<int>(cin), istream_iterator<int>());
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
就是编译不了!
但是如果我这样构建它:
istream_iterator<int> beg(cin), end;
vector<int> vec(beg, end);
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
有效。
为什么?我不能使用临时变量来构造向量吗?如果可以,但为什么我使用 std::copy 时可以这样做?
ps:我是在vs2005下编译的,使用了如下头文件:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
不幸的是,这是一个函数声明:
vector<int> vec(istream_iterator<int>(cin), istream_iterator<int>());
这是一个名为 vec
的函数,returns 一个 vector<int>
的值,它有两个参数:一个 istream_iterator<int>
,形式参数名称为 cin
,以及一个没有形式参数名称的函数 returns 和 istream_iterator<int>
,并且不带任何参数。
为什么?
基本上,在 C++(和 C)中,如果一段代码可以解释为声明,那么它就是。
根据N3936::6.8.1 [stmt.ambig]:
There is an ambiguity in the grammar involving expression-statements and declarations: An expressionstatement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [ Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. This disambiguates many examples. [ Example: assuming T is a simple-type-specifier (7.1.6),
T(a)->m = 7; // expression-statement
T(a)++; // expression-statement
T(a,5) << c; // expression-statementT(*d)(int); // declaration
T(e)[5]; // declaration
T(f) = { 1, 2 }; //declaration
T(*g)(double(3)); // declarationIn the last example above, g, which is a pointer to T, is initialized to double(3). This is of course ill-formed for semantic reasons, but that does not affect the syntactic analysis. —end example ]
如何修复
我们所需要的只是使编译器无法将代码视为函数声明的东西。
在参数周围添加额外的括号可以清楚 编译器认为我们打算成为构造函数参数名称不能是参数声明。
vector<int> vec((istream_iterator<int>(cin)), istream_iterator<int>());
如您的解决方案所示,使用命名变量作为构造函数参数。