我有一个函数,它接受一个指向自定义类对象的指针(实际上是指向基类的指针,这样多态性就可以工作)。然而,在调用例程中,该对象仅用于该调用的目的,即是临时的。例如:
class A { /** stuff */ };
class B : public A { /** stuff */ };
void doSomething( const A* const _p ) { /** stuff */ }
void callingRoutine()
{
A* tempPointer = new B;
doSomething( tempPointer );
delete tempPointer;
}
现在,因为在B
的调用中我真的只需要doSomething
类型的对象,有没有办法在一行中完成?做
doSomething( new B );
创建内存泄漏(valgrind这样说)。或者
doSomething( &B );
是推荐的方式吗?后者编译但会发出有关将指针传递给临时对象的警告。这就是我想要的,但这样安全吗?
答案 0 :(得分:5)
如果您可以更改被调用函数的签名,请将其更改为:
void doSomething( A const& obj );
然后你可以用:
来调用它doSomething( B() );
如果你不能,应该声明一个局部变量:
void callingRoutine()
{
B temp;
doSomething( &temp );
}
如果调用函数更长,那么如果temp是有问题的话
如果没有立即销毁,您可以将其附加在其他{...}
:
void callingRoutine()
{
{
B temp;
doSomething( &temp );
}
// More code here...
}
但是,一般来说,如果有必要,你的职能是 可能太长了。
答案 1 :(得分:4)
最干净的方法是
B b;
doSomething(&b);
但你应该写的东西取决于doSomething
函数的作用。如果可以在b
结束时破坏callingRoutine
,那么这是更快更清洁的方法,因为在堆栈上分配比new
更快,并且不需要你之后删除b
。
答案 2 :(得分:3)
在您的情况下,您可以使用自动变量(在堆栈上)
void callingRoutine()
{
B obj;
doSomething( &obj );
} // obj is destroyed automatically
这不会发出警告。此外,只有当您真的希望在功能范围之外引用/访问存储器地址更长时间时,才应使用new
。在功能块中,使用new
进行分配是没有意义的。
请参阅Bjarne页面中的this link,他在那里指出了您的确切示例。
顺便说一句,如果你只需要一行,那么解决方案就不会干净,但这是一个解决方法:
B obj; doSomething( &obj );
答案 3 :(得分:3)
我有点惊讶没有人指出明显的:
void callingRoutine()
{
doSomething(&B());
}
我不得不怀疑需要传递指向对象的指针的整体设计,但是当它完成时你显然忽略了它操作的对象,但是如果你确定你想要什么以及你剩下的什么这样做,这似乎是实现它的最简单,最直接的方式。
答案 4 :(得分:1)
下面可能会有什么?
void doSomething( std::auto_ptr<A> _p ) { /** stuff */ }
void callingRoutine()
{
doSomething(std::auto_ptr<A>(new B));
}
答案 5 :(得分:1)
解决问题的最简单方法是更改代码,如下所示:
void callingRoutine()
{
B temp;
doSomething( &temp );
}
这是有效的,因为你只需要在doSomething()中进行多态访问,这可以通过获取地址来传递指向temp的事实来保证。
答案 6 :(得分:0)
将指针传递给临时对象通常是一个坏主意,因为在被调用者完成使用之前可能会销毁该对象。在您的示例中,doSomething()
应该在对象被删除或超出范围之前返回,因此,直到doSomething
不存储对该对象的任何引用,这不是问题。
答案 7 :(得分:0)
您可以在调用或表达式的持续时间内将临时值(r值)转换为l值:
template<class T>
inline T& l_value(T const& t)
{
return const_cast<T&>(t);
}
struct A {};
void doSomething(const A*);
void foo()
{
doSomething(&l_value(A()));
}