由于C++编译器的分析机制所导致的声明问题

假设我们想声明一个STL的vector类型的变量,读入文件里的信息:

std::ifstream in("data.txt");
std::vector<int> data(std::istream_iterator<int>(in),std::istream_iterator<int>());

之后我们引用data的元素时,会发现编译器报错。为什么呢,让我们来分析一下:

在此时的编译器看来,我们实际上声明的是一个函数,它的返回值是vector,参数有两个,第一个参数为一个istream_iterator对象,第二个参数为一个无参数的,返回istream_iterator的函数指针

造成这种现象是因为C++的编译机制会尽量将语句解释为函数声明。

这种现象实际上并不稀奇,比如如下一段代码你或许也见过:

class Widget
{...};    //内部有一个默认构造函数
Widget w();//此时编译器会将w看做一个函数声明

解决这种问题的一个方法是给第一个参数加一个括号:

std::vector<int> data((std::istream_iterator<int>(in)),std::istream_iterator<int>());

C++不允许给函数的形参加括号,但允许给函数的实参加括号。这样一来编译器就确认data是一个vector对象了。

当然,治本的方法还是使用临时变量:

std::ifstream in("data.txt");
std::istream_iterator dataBegin(in);
std::istream_iterator dataEnd;
std::vector<int> data(dataBegin,dataEnd);

此博客内容参考《Effective STL》第6条。

时间: 2024-12-28 00:01:26

由于C++编译器的分析机制所导致的声明问题的相关文章

C++编译器最烦人的分析机制

 下面这行代码声明了一个带double参数并返回int的函数: int f(double d); 下面这行做了同样的事情,参数d两边的括号是多余的,会被忽略: int f(double (d)); 下面这行声明了同样的函数,只是它省略了参数名称: int f(double); 这三种形式除了第二种,我们应该都很熟悉. 下面我们在看三个函数声明.第一个声明了一个函数g,它的参数是一个指向不带任何参数的函数的指针,该函数返回double值: int g(double (*pf)()); 有另外一

findstr的命令行分析机制

来源:http://www.cn-dos.net/forum/viewthread.php?tid=21167&fpage=1&highlight=findstr willsort 版主 To All: 问题缘起于bsijl一篇关于findstr错误过滤的主题[1],当时因为无法找到原因,所以只能推测 /g 开关存在某些问题. 近日,因为编写一个debuger代码,再次使用了 findstr/g ,结果遇到了同样的问题[2].经过仔细的测试[3]后,发现是 findstr 特殊的命令行分析

【S6】当心C++编译器最烦人的分析机制

1.考虑一个包含int的文件,复制到list,如下: ifstream dataFile("ints.bat"); list<int> data(istream_iterator<int>(dataFile),istream_iterator<int>());2.上面的代码不是预期的行为.3.先从最简单开始,声明方法 int f(double d); 等价的写法有 int f (double (d)); int f (double); 也就是说,形参

C++编译器函数模版机制剖析 - 函数模版的本质

思考:为什么函数模板可以和函数重载放在一块.C++编译器是如何提供函数模板机制的? demo 1 #include <cstdio> #include <iostream> using namespace std; // 1.cpp // g++ -S 1.cpp -o 1.s template <typename T> void myswap(T &a, T &b) { T c = 0; c = a; a = b; b = c; cout <&l

详解java中CAS机制所导致的问题以及解决——内存顺序冲突

[CAS机制] 指的是CompareAndSwap或CompareAndSet,是一个原子操作,实现此机制的原子类记录着当前值的在内存中存储的偏移地址,将内存中的真实值V与旧的预期值A做比较,如果不一致则说明内存中的值被其他线程修改过了,返回false,否则将新值B存入内存. Java内部是使用本地调用类unsafe实现的. Java原子类底层原理就是采用CAS机制. 可能会出现什么问题 aba问题: 线程1取出A之后被阻塞了,此时线程2把内存中A改为B,一系列操作后又改为A,此时线程1恢复执行

图片无限轮播由于ViewPager的预加载机制所导致的问题

分类和回归是分析预测中最古老的话题.支持向量机.逻辑回归.朴素贝叶斯算法.神经网络和深度学习都属于分类和回归技术. 本章将重点关注决策树算法和它的扩展随机决策森林算法,这两个算法灵活且应用广泛,即可用于分类问题,也可用于回归问题.更令人兴奋的是,它们可以帮助我们预测未来,至少是预测我们尚不肯定的事情.比如,根据线上行为来预测购买汽车的概率,根据用词预测邮件是否是垃圾邮件,根据地理位置和土壤的化学成分预测哪块耕地的产量可能更高. 总体实现无限轮播的思想,其实和网上大部分的思路都是相同的,设置一个I

kernel panic 分析(camera导致的mem越界)

这个panic是由CTS测试的时候发现的,panic的log如下: [ 2212.531425] c3 3279 (logcat) Unable to handle kernel paging request at virtual address 2b2c2c2b2b292a2a [ 2212.541032] c3 3279 (logcat) pgd = ffffffc00d5f5000 [ 2212.545910] [2b2c2c2b2b292a2a] *pgd=000000000000000

C编译器剖析_4.4 语义检查_外部声明_类型结构的构建(2)

在这一小节中,我们将对形如第3章图3.3.17所示的结构体语法树进行语义检查,从而构建结构体的类型结构. 图3.3.17 ParseStructOrUnionSpecifier()构建的语法树 我们在第2章中给出了以下结构体struct Data对应的类型结构,如图2.4.4所示.为了阅读方便,我们重新给出这2幅图,由图示我们也能较清楚地预览本节的起点和终点. struct Data{ int abc:8; int def:24; double f; } dt; 图2.4.4   结构体的类型结

[C++]高效使用容器的一些建议

高效使用容器的一些建议 本文介绍一些在使用容器中常见的问题,并给出其解决方法从而提升对容器的认识和使用. 1. 不要试图编写独立于容器类型的代码 STL是以泛化原则为基础的:数组被泛化为"以其包含的对象的类型为参数"的容器:函数被泛化为"以其使用的迭代器的类型为参数"的算法:指针被泛化为"以其指向的对象的类型为参数"的迭代器. 如果我们试图编写独立于容器类型的代码,例如编写一个既能够满足序列容器又满足关联容器的代码,我们最后会发现我们使用的只是他