假设有个文件里面记录的一系列的 int 值,现在我们想把这些数值存到一个 List 里面,结合 Item 5, 我们可能会写出下面的代码:

ifstream dataFile("ints.data");
list<int> data(istream_iterator<int>(dataFile), // Start of iterator
istream_iterator()); // End of iterator

这段代码可以编译,但运行时并不工作,它不会去调用 list 的构造函数,从而不会生成我们想要的这个 List。

问题,出在 C++ 对代码的解析上。

假设我们需要声明一个函数,该函数接受 double 类型参数并返回 int 类型,C++ 里面,下面三种方法是等效的:

1: int f(double d);  // Old C style.
2: int f(double(d)); // Function style casts.
3: int f(double); // Same as first but skip parameter.

如果我们要声明另外一个函数,该函数同样返回 int,但接受的参数是一个无参数但返回 double 的函数的指针,则下面的声明是等效的:

4: int g(double (*pf)()); // g takes a pinter to a function as paramter.
5: int g(double pf()); // same as above
6: int g(double ()); // same as above, but parameter (function name) skipped.

观察 1 ~ 6 我们可以看到“ 括号”在不同位置时候的不同作用:

  • 参数 周围的括号可以被忽略
  • 单独 的括号实际上意味着这是一个函数指针的参数列表!

了解了这个区别之后再返回来看最开始的那个声明:

list<int> data(istream_iterator<int>(dataFile), istream_iterator<int>());

这个声明定义了一个返回 list<int> 的函数,该函数接受两个参数:

  • 第一个参数名为 dataFile,类型为 istream_iterator<int>,dataFile 两遍的括号可以忽略。
  • 第二个参数是一个函数指针,该函数不接受参数但返回一个 istream_iterator<int>。

这个和我们最开始想象的完全不一样,而产生分歧的原因就在于 C++ 对代码的解析上:

只要表达式可以被解析成 函数 ,那么该表达式 就会被编译器解析成函数 !

想象一下下面这段代码,相信很多人都写出来过,但是它能编译么?

 7: class Widget
8: {
9: public:
10: Widget(){}
11: virtual ~Widget(){}
12: void Show(){}
13: };
14:
15: Widget w();
16: w.Show();

上面片段的第 8 行实际上不是声明了一个 Widget 对象,而是声明了一个用来返回 Widget 对象的函数,第 9 行自然也就出错了。

理解了上面的内容,也就可以想想怎么解决开始时提出的问题了:给形参声明加上括号不合法,但给函数调用的实参加括号是合法的,通过适当的添加括号,问题得以解决:

1: list<int> data((istream_iterator<int>(dataFile)),
2: istream_iterator<int>());

这里第一个参数周围添加了多余的括号,假设编译器仍然认为 data() 是一个函数声明,则第一个形参周围就被添加了括号,这是一个非法的行为,所以编译器会丢掉这种可能,转而匹配下一种可能得匹配,认为该表达式声明了一个 list<data> 的变量,并调用适当的区间函数(Item 5)来进行初始化。

但并非所有的编译器都支持这种匿名对象,如果编译器不支持,我们需要下面的这种显示的写法:

1: ifstream dataFile("ints.dat");
2: istream_iterator<int> dataBegin(dataFile);
3: istream_iterator<int> dataEnd;
4: list<int> data(dataBegin, dataEnd);

这种写法应该通用。

Effective STL 笔记: Item 6--Be alert for C++'s most vexing parse的更多相关文章

  1. Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer

    Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...

  2. Effective STL 笔记 -- Item 9: Choose carefully among erasing options

    假设有一个容器中存放着 int ,Container<int> c, 现在想从其中删除数值 1963,可以有如下方法: 1: c.erase(remove(c.begin(), c.end ...

  3. C++学习书籍推荐《Effective STL(英文)》下载

    百度云及其他网盘下载地址:点我 作者简介 Scott Meyers is one of the world's foremost authorities on C++, providing train ...

  4. STL笔记(6)标准库:标准库中的排序算法

    STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...

  5. Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value

    Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...

  6. Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据

    Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...

  7. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  8. Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor

    Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor */--> div ...

  9. Effective STL 学习笔记: Item 22 ~ 24

    Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...

随机推荐

  1. ZJOI2012网络 题解报告【LCT】

    题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环,同色的环指相同颜色的边构成的环. 在这 ...

  2. Hive(六)hive执行过程实例分析与hive优化策略

    一.Hive 执行过程实例分析 1.join 对于 join 操作:SELECT pv.pageid, u.age FROM page_view pv JOIN user u ON (pv.useri ...

  3. Codeforces 717.F Heroes of Making Magic III

    F. Heroes of Making Magic III time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

  4. Git之安装及使用

    学习使用Git来管理平时自己写的demo代码和阅读的一些源码,因为一直在windows中操作所以开始学习用Git Bash操作在github上的代码.git命令和svn命令是很相似的,我觉得没有必要把 ...

  5. C#中调用Dll动态链接库

    C#中调用Dll动态链接库 起始 受限于语言的不同,我们有的时候可能会用别人提供的函数及方法 或者其他的什么原因.反正就是要调!!! 恰巧别人所使用的的语言跟自己又不是一样的 这个时候想要调用别人的函 ...

  6. 题解 P2472 【[SCOI2007]蜥蜴】

    P2472 [SCOI2007]蜥蜴 题目背景 07四川省选 题目描述 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱 ...

  7. MVC网站发布到 IIS

    接下来将发布成功的站点部署到iis7.0. 步骤如下: 1. 安装 Microsoft .net FrameWork 4.0安装包(网站开发时候使用的就是.net framework4.0框架); 2 ...

  8. centos7 ffmpeg安装

    #Nux Dextop库依赖于EPEL库,所有要先安装EPEL库yum -y install epel-release #安装Nux Dextop库rpm -Uvh http://li.nux.ro/ ...

  9. centos7 samba匿名访问设置

    [global] workgroup = WORKGROUP server string = Samba Server %v netbios name = centos security = user ...

  10. 批量提取图片主要3个颜色匹配中文名字并写入到excel设置对应颜色的背景

    from gevent import monkey monkey.patch_all() import gevent from haishoku.haishoku import Haishoku im ...