C ++如何将指向临时对象(在堆上)的指针传递给函数?

时间:2011-08-09 09:01:30

标签: c++ argument-passing

我有一个函数,它接受一个指向自定义类对象的指针(实际上是指向基类的指针,这样多态性就可以工作)。然而,在调用例程中,该对象仅用于该调用的目的,即是临时的。例如:

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 );

是推荐的方式吗?后者编译但会发出有关将指针传递给临时对象的警告。这就是我想要的,但这样安全吗?

8 个答案:

答案 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()));
}