临时对象,函数参数和隐式转换

时间:2009-07-21 09:09:07

标签: c++

在以下情形中:

struct Foo
{
   // ...
   operator Bar() {... }  // implicit cast to Bar
}

Foo GetFoo() { ... }
void CallMeBar(Bar x) { ... }

// ...
CallMeBar( GetFoo() );

[edit]修复了演员,d'oh [/ edit]

GetFoo返回Type Foo的临时对象。在CallMe返回之前,此对象是否存在?标准说了什么?

我理解如果CallMe接受Foo,临时对象在CallMe返回之前不会被销毁。但是,我不确定隐式转换会改变这一点,只保证临时Bar能够存活。


典型的情况是Foo = CString,Bar = char *,即Bar引用由Foo持有(并由其释放)的数据。

4 个答案:

答案 0 :(得分:7)

无论演员如何,由于C ++标准,临时对象将“生存”到CallMe()函数的调用中:

12.2.3 [...]临时对象被作为评估全文(1.9)的最后一步而被销毁,其中(词汇)包含创建它们的点。 [...]

1.9.12 fullexpression 是一个表达式,不是另一个表达式的子表达式。

答案 1 :(得分:2)

它会存活,但依赖于这个事实可能会令人困惑,并且可能会导致代码的客户端达到C ++标准,在Stack Overflow上提出问题等等;-)。例如,有人做了什么:

Bar b = GetFoo();
CallMeBar(b);

这一次,Foo在调用CallMeBar之前已经消失了,但大多数程序员都希望转换创建一个独立的对象,因此代码的行为与:

CallMeBar(GetFoo());

这就是为什么std::string没有对char*进行隐式转换的原因,与CString转换为LPCTSTR不同。相反,std::string具有c_str()成员函数,它具有相同的约束,但在调用代码时使其更明显,它不是真正的转换:

CallMePtr(GetString().c_str());   // OK

char* p = GetString().c_str();    // Bad
CallMePtr(p);                     // Badness manifests

const string &s = GetString();    // use "the most important const"
CallMePtr(s.c_str());             // Best be on the safe side

答案 2 :(得分:1)

只要您按值返回它们,它们就会一直存在,直到CallMeBar完成。

但是,您的演员操作员稍微偏离了一点。应该是:

struct Foo
{
   // ...
  operator Bar() {... }  // implicit cast to Bar
}

参见例如http://msdn.microsoft.com/en-us/library/ts48df3y(VS.80).aspx

答案 3 :(得分:1)

我倾向于想到它 - 魔术角色是分号。分号触发析构函数。