C++ 如何防止创建临时对象?
我有类似的代码:C++ 如何防止创建临时对象?,c++,C++,我有类似的代码: MyClass createInstance() { MyClass t; t.setValue(20); return t; } int main() { MyClass primary; primary.setValue(30); primary = createInstance(); } 我的问题是createInstance()创建了一个临时文件,以后会删除它。在我的例子中,它不使用RVO,我必须使用三个规则(因为我
MyClass createInstance()
{
MyClass t;
t.setValue(20);
return t;
}
int main()
{
MyClass primary;
primary.setValue(30);
primary = createInstance();
}
我的问题是createInstance()
创建了一个临时文件,以后会删除它。在我的例子中,它不使用RVO,我必须使用三个规则(因为我的类有一个指向数据成员的指针),并且我必须对兆字节的数据进行深度复制。
我想知道什么是最好的方法,以防止创建一个临时的
此外,我将这个MyClass作为另一个类的成员,并且我希望防止指针的间接寻址以及在父类的析构函数中手动删除它的要求
例如,我可以使用指针(这需要我显式调用析构函数:
MyClass *createInstance()
{
MyClass *t = new MyClass();
t->setValue(20);
return t;
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = createInstance();
}
或者我可以使用一个成员函数:
void MyClass::createNewInstance()
{
~MyClass();
init();
setValue(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
primary.createNewInstance();
}
或者我一般不允许分配/复制:
void MyClass::createInstance()
{
setValue(20);
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = new MyClass();
primary->createInstance();
}
我遗漏了什么吗?就像帕迪说的,你怎么知道它没有使用RVO? 如果不是在调试模式下,编译器会做很多事情来优化代码。 但是,在creatInstance函数中,您创建了一个本地对象,并对其调用了一个成员函数使其难以优化,因为编译器会认为,局部对象比返回值更有用。显然,我们知道局部t可以优化,但编译器可能无法从上下文中分析这一点 而且,根据“creatInstance”的含义,您似乎只想创建一个实例并返回它。因此,如果您的构造函数允许直接设置值,您可以使用RVO:
MyClass creatInstance()
{
return MyClass(20); // if your constuctor makes it possible
}
then, your code will be optimized to this:
// C++ psuedocode
void creatInstance(MyClass* ptr)
{
new (ptr) MyClass(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
// primary = createInstance();
MyClass __temp; // default constructor not called!
creatInstance(&__temp);
primary.operator=(__temp);
// destruct the __temp
}
您可能认为,它仍然必须创建临时对象并销毁它,是的,但是在原始代码中,您将创建两个临时对象并销毁它们,一个在主堆栈帧中,一个在creatInstance函数的堆栈帧中
如果你无法承受创建临时对象和这些东西的成本,我认为你可以改变你的想法:
void modifyInstance(Myclass& objToBeModified)
{
objToBeModified.setValue(20);
// do any change
}
and call it by : modifyInstance ( primary );
by this way, the temporary object creation is definitely prevented!
毕竟,您只想通过调用函数来更改主函数,为什么不像上面那样直接编写它呢?您不能(N)RVO复制到预先存在的对象中。优化的目的是使用另一个新创建的对象,而不是复制,但在这种情况下,编译器不能保证赋值对象不会保留一些现有状态(例如)
我希望MyClass primary(createInstance());
能够为您启用NRVO
如果你真的需要从一个创建函数中分配你的选择至少有两个:你可以创建一个临时的,然后交换,避免数据拷贝。与C++ 11交替,你可以将代码>移动< /C>到现有的对象。< /P>你可以使用新的C++吗?注意,你可以使用Booo::SydDypTR,不用担心删除它。但是你为什么要担心这个?你怎么知道它没有使用RVO?@paddy它调用临时的析构函数。
swap
或move
将返回值中的数据移动到primary
。如果你可以使用C++11,请使用移动语义,如user814628所述;否则你可以mentswap
或类似于move
/rvalue refs的东西,例如通过包装返回值(并为移动包含数据的包装类型提供赋值操作)。兆字节?除非使用显式的copy
方法,否则绝不允许复制此类对象。简单!