在以下情形中:
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持有(并由其释放)的数据。
答案 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)
我倾向于想到它 - 魔术角色是分号。分号触发析构函数。