LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 621|回复: 7

有关匿名对象的问题

[复制链接]
发表于 2004-5-29 20:12:33 | 显示全部楼层 |阅读模式
这样的代码可以编译通过

  1. char buff[1024];
  2. string str(buff);
  3. istringstream iss (str);
  4. int a;
  5. iss >> a;
复制代码

但是这样的代码却无法通过编译,为什么?

  1. char buff[1024];
  2. istringstream iss(string(buff));
  3. int a;
  4. iss >> a;
复制代码

istringstream 的构造函数是原型是:

  1. explicit istringstream ( openmode mode = in );
  2. explicit istringstream ( const string & str, openmode mode = in );
复制代码

难道是对于引用作参数是,不能传匿名对象?
发表于 2004-5-29 21:11:28 | 显示全部楼层
应该不是吧

这段代码用Dev-C++编译通过:

  1. #include <iostream>
  2. #include <string>
  3. #include <cstdlib>

  4. using namespace std;

  5. class CHello{
  6. public:
  7.     CHello(){}
  8.     //explicit
  9.     CHello(const string & _str)
  10.     {
  11.         str=_str;
  12.     }
  13.     string & get_str(void)
  14.     {
  15.         return str;
  16.     }
  17. private:
  18.     string str;
  19. };

  20. int main(int argc,char ** argv)
  21. {
  22.     CHello hello(string("1234567890"));
  23.     cout<<hello.get_str()<<endl;

  24.     system("PAUSE");
  25.     return 0;
  26. }
复制代码


再好好想想~~~:confused:
 楼主| 发表于 2004-5-29 23:41:57 | 显示全部楼层
最初由 _z_ 发表
应该不是吧

这段代码用Dev-C++编译通过:


再好好想想~~~:confused:

也许我的这个推测不对,但是:
这个没法通过编译

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <sstream>
  4. #include <fstream>
  5. using namespace std;

  6. int main(int argc, char *argv[])
  7. {
  8. char buff[1024];
  9. istringstream iss(string(buff));
  10. int a;
  11. iss >> a;

  12.   system("PAUSE");       
  13.   return 0;
  14. }
复制代码

  1. 这个却是可以的:
  2. #include <iostream>
  3. #include <stdlib.h>
  4. #include <sstream>
  5. #include <fstream>
  6. using namespace std;

  7. int main(int argc, char *argv[])
  8. {
  9. char buff[1024];
  10. string str(buff);
  11. istringstream iss (str);
  12. int a;
  13. iss >> a;


  14.   system("PAUSE");       
  15.   return 0;
  16. }
复制代码

我也是使用dev-cpp编译的。
你的代码我没有编译,估计是可以的,因为在这之前我自己也做过测试。发现不是我说的那个原因。
发表于 2004-5-30 11:27:29 | 显示全部楼层
照我分析:
首先你的 string(buff) 返回了一个匿名对象(暂时叫它 tmp 吧),而它的生命周期只是从 istringstream iss 的 ctor 的调用到返回,也就是 iss 这个对象一旦被构造出来,tmp 就灰飞烟灭了,而 iss 还欢欢喜喜地拿着一个(dangling 的) const string& 当宝。

其次,从 ctor 的角度分析,凡是 C++ 中的函数(比如 Z Y::bar(X a)),它的实参总是 a 的副本,即:
如果调用以 y.bar(b) 的形式调用 Z Y::bar(X a) 这个函数,那么会构造一个临时对象(暂称其为 tmp_a)。在你的问题中 tmp_a 是一个 const string& 对象,不用调用 copy ctor 或者其他转型 ctor。所以 iss 不会获得一个实实在在的 life cycle 比它长或和它一样的 string。

综上,从 iss 的角度考虑, 临时对象 tmp (string)极可能不能转型为 tmp_a (const string&)。否则 iss 到时候只能 SIGSEGV 了。

你的这个问题可能在 C++ Gotchas 里有解释,不过我还没买这本书。
anonymous temporaries  - initialization of a reference formal argument

这是书的索引:
http://www.awprofessional.com/co ... x/dewhurstindex.pdf
 楼主| 发表于 2004-5-30 11:40:17 | 显示全部楼层
最初由 chaisave 发表
照我分析:
首先你的 string(buff) 返回了一个匿名对象(暂时叫它 tmp 吧),而它的生命周期只是从 istringstream iss 的 ctor 的调用到返回,也就是 iss 这个对象一旦被构造出来,tmp 就灰飞烟灭了,而 iss 还欢欢喜喜地拿着一个(dangling 的) const string& 当宝。

其次,从 ctor 的角度分析,凡是 C++ 中的函数(比如 Z Y::bar(X a)),它的实参总是 a 的副本,即:
如果调用以 y.bar(b) 的形式调用 Z Y::bar(X a) 这个函数,那么会构造一个临时对象(暂称其为 tmp_a)。在你的问题中 tmp_a 是一个 const string& 对象,不用调用 copy ctor 或者其他转型 ctor。所以 iss 不会获得一个实实在在的 life cycle 比它长或和它一样的 string。

综上,从 iss 的角度考虑, 临时对象 tmp (string)极可能不能转型为 tmp_a (const string&)。否则 iss 到时候只能 SIGSEGV 了。

你的这个问题可能在 C++ Gotchas 里有解释,不过我还没买这本书。
anonymous temporaries  - initialization of a reference formal argument

这是书的索引:
http://www.awprofessional.com/co ... x/dewhurstindex.pdf

我前面也认为是生命周期的问题。
但是你看这一段代码:

  1. #include <iostream>
  2. #include <stdlib.h>

  3. using namespace std;

  4. class anon
  5. {
  6. public:
  7.     anon(){ cout << "anon object was constructed\n";}
  8.     ~anon(){ cout << "anon object was destructed\n";}
  9. };

  10. void fun(const anon& a)
  11. {
  12.     cout << "fun was called\n";
  13. }

  14. int main(int argc, char *argv[])
  15. {
  16.   fun(anon());
  17.   return 0;
  18. }

复制代码

它的输出:

  1. anon object was constructed
  2. fun was called
  3. anon object was destructed
复制代码

从这里看出,匿名对象的生命周期是整个函数的调用过程。
发表于 2004-5-30 12:08:38 | 显示全部楼层
呵呵,我当然同意您的观点:
匿名对象的生命周期是整个函数的调用过程

,但是也正如我前面说的,
而它的生命周期只是从 istringstream iss 的 ctor 的调用到返回

仅仅是局限于 ctor 这个函数的调用过程。虽然 ctor 可以心安理得的返回。但是 iss 可能的后继操作可能造成 SEGV 的灾难性后果。

所以这样分析,当用一个非 POD 临时对象的引用(如果不是引用的话,就可以了)构造一个 class object 是有问题的。当然,小弟都是站在程序的观点来分析问题的,并没有 ISO standard 的条文作依据。所以仅是“于情”,而非“于理”。
 楼主| 发表于 2004-5-30 12:41:59 | 显示全部楼层

It sounds reasonable

Thanks
我再找找其它的资料看看。
发表于 2004-5-30 16:14:54 | 显示全部楼层
最初由 chaisave 发表
呵呵,我当然同意您的观点:

,但是也正如我前面说的,

仅仅是局限于 ctor 这个函数的调用过程。虽然 ctor 可以心安理得的返回。但是 iss 可能的后继操作可能造成 SEGV 的灾难性后果。

所以这样分析,当用一个非 POD 临时对象的引用(如果不是引用的话,就可以了)构造一个 class object 是有问题的。当然,小弟都是站在程序的观点来分析问题的,并没有 ISO standard 的条文作依据。所以仅是“于情”,而非“于理”。


可是编译器一般不会检查到“以后会造成SEGV的代码”吧。
编译不通过说明还有别的原因。
俺猜地 :p
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表