gentoo emerge unable to sync
Effective STL 笔记 -- Item 9: Choose carefully among erasing options

Effective STL 笔记: Item 6--Be alert for C++'s most vexing parse

tubo posted @ 2014年9月03日 00:10 in 未分类 , 691 阅读

 

假设有个文件里面记录的一系列的 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);

这种写法应该通用。

Alyssa 说:
2023年1月07日 01:09

C++'s most vexing parse is a term used to describe the the way in which the C++ compiler can interpret code in ways that the programmer did not intend. This best online engagement rings store can lead to errors and unexpected behaviour. The best way to avoid these problems is to be aware of them and to use clear and concise code.

meidir 说:
2023年10月05日 07:35

Wow, incredible blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your site is excellent, let alone the content! 花藝師

meidir 说:
2023年10月31日 04:38

Wow that was strange. I just wrote an really long comment but after I clicked submit my comment didn’t appear. Grrrr… well I’m not writing all that over again. Anyway, just wanted to say wonderful blog! 玫瑰花

 

================

 

One of the things I enjoy regarding reading websites such as this, is that there aren’t any spelling or lexical errors! Causes it to be tough about the readers sometimes. Very good work upon that and also the subject of this website. Many thanks! 開張花籃花牌

 

================

 

Hi, I just found your web site via google. Your post is truly relevant to my life currently, and I’m really delighted I found your website. 訂花推介

 

================

 

Hello, this is truly a magnificent article, and I enjoy the meticulous detail you provide. I will certainly link back to this entry in my newest blog post. 網上訂花

meidir 说:
2023年11月11日 03:44

kitchen furnitures need to be well maintained that is why we always coat them with clear coat varnishes to protect them from the elements., جامعات خاصة مصر

meidir 说:
2023年11月16日 06:22

i use both gold and silver bracelets because for me, they are both great bracelets to wear“ https://lightinfitness.com/

meidir 说:
2023年11月23日 06:53

I am glad to be a visitant of this perfect blog, regards for this rare info! 手機回收

 

===============

 

I have not checked in here for a while as I thought it was getting boring, but the last few posts are really great quality so I guess I will add you back to my everyday bloglist. You deserve it my friend. 先達iphone回收價

 

================

 

I not to mention my buddies ended up viewing the best points from the website while immediately developed a horrible feeling I had not expressed respect to the site owner for those secrets. Those young boys had been for that reason excited to see all of them and have now absolutely been taking pleasure in those things. Many thanks for simply being considerably thoughtful and then for making a decision on some terrific topics most people are really needing to learn about. My very own honest regret for not expressing appreciation to you sooner. iphone13回收價

 

================

 

Excellent commentary on that subject. We appreciate your knowledge that you really to leave out with us! iphone回收價每日更新


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter