我有一个按值返回对象的函数。接收者变量需要调用该对象上的外向转换运算符。如果我在返回语句 (RVO) 中构造返回的对象,则在外向转换运算符之前调用其析构函数。但是,如果我命名对象并返回它,则在对象被破坏之前调用外向转换运算符。这是为什么?
#include <iostream>
class Ref {
public:
Ref(int * ptr) : iptr(ptr) {
std::cout << "Ref Constructed at: " << long(this) << " Pointing to: " << long(ptr) << '\n';
}
Ref(Ref & ref) : iptr(ref) {
std::cout << "Ref Moved to: " << long(this) << '\n';
ref.iptr = nullptr;
}
operator int () {
std::cout << "Ref-To int: Temp at: " << long(iptr) << '\n';
return *iptr;
}
operator int* () {
std::cout << "Ref-To int*: Temp at: " << long(iptr) << '\n';
return iptr;
}
~Ref() {
delete iptr;
std::cout << "Ref at: " << long(this) << " Deleted: " << long(iptr) << '\n';
}
private:
int * iptr;
};
Ref foo() {
int * temp = new int(5);
Ref retVal(temp);
std::cout << "Return named Ref\n";
return retVal;
}
Ref bar() {
int * temp = new int(5);
std::cout << "Return anonymous Ref\n";
return Ref(temp);
}
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "********* Call foo() *************\n";
int result = foo();
std::cout << "\n********* Call bar() *************\n";
int result2 = bar();
return 0;
}
输出是:
********* Call foo() *************
Ref Constructed at: 2356880 Pointing to: 5470024
Return named Ref
Ref-To int*: Temp at: 5470024
Ref Moved to: 2356956
Ref at: 2356880 Deleted: 0
Ref-To int: Temp at: 5470024
Ref at: 2356956 Deleted: 5470024
********* Call bar() *************
Return anonymous Ref
Ref Constructed at: 2356680 Pointing to: 5470024
Ref-To int*: Temp at: 5470024
Ref Constructed at: 2356968 Pointing to: 5470024
Ref at: 2356680 Deleted: 5470024
Ref-To int: Temp at: 5470024
Press any key to continue . . .
当 bar() 被调用时,引用在调用转换运算符之前被删除,并且它崩溃。另外,我不明白为什么在构建返回值时会调用 Ref 到 int* 的转换。