1

我经常使用 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>
4

1 回答 1

2

不幸的是,这是一个函数声明:

vector<int> vec(istream_iterator<int>(cin), istream_iterator<int>());

它是一个名为 的函数vec,它按值返回 avector<int>并接受两个参数:istream_iterator<int>一个形式参数名称为cin的函数,以及一个没有形式参数名称的函数,它返回一个istream_iterator<int>,并且不接受任何参数。

为什么?

基本上,在 C++(和 C)中,如果一段代码可以解释为声明,那么它就是。

根据 N3936::6.8.1 [stmt.ambig]:

在涉及表达式语句和声明的语法中存在歧义:将函数样式显式类型转换 (5.2.3) 作为其最左边的子表达式的表达式语句与第一个声明符以 (. 开头的声明无法区分。如果语句是声明。[ 注意:为了消除歧义,可能必须检查整个语句以确定它是表达式语句还是声明。这消除了许多示例的歧义。[ 示例:假设 T 是简单类型-说明符(7.1.6),

T(a)->m = 7; // 表达式语句
T(a)++; // 表达式语句
T(a,5) << c; // 表达式语句

T(*d)(int); // 声明
T(e)[5]; // 声明
T(f) = { 1, 2 }; //声明
T(*g)(double(3)); // 宣言

在上面的最后一个例子中,指向 T 的指针 g 被初始化为 double(3)。由于语义原因,这当然是格式错误的,但这并不影响句法分析。—结束示例]

如何修复它

我们所需要的只是使编译器无法将代码视为函数声明。

  1. 在参数周围添加额外的括号可以让编译器清楚地知道我们打算作为构造函数参数名称的内容不能是参数声明。

    vector<int> vec((istream_iterator<int>(cin)), istream_iterator<int>());

  2. 正如您的解决方案所示,使用命名变量作为构造函数参数。

于 2015-06-24T02:53:57.467 回答