将指向临时对象(在堆上)的指针传递给函数的方法

C++ Ways to pass a pointer to a temporary object (on the heap) to a function?

本文关键字:指针 方法 函数 临时对象      更新时间:2023-10-16

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

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

是推荐的方法吗?后者可以编译,但会对将指针传递给临时对象发出警告。这是我想做的,但这样安全吗?

如果可以更改被调用函数的签名,则将其更改为:

void doSomething( A const& obj );

然后你可以用:

doSomething( B() );

如果不能,应该声明一个局部变量:

void callingRoutine()
{
    B temp;
    doSomething( &temp );
}

如果调用函数较长,并且如果temp是,则存在问题不立即销毁,你可以将其封装在附加的{...}:

void callingRoutine()
{
    {
        B temp;
        doSomething( &temp );
    }
    //  More code here...
}

一般来说,如果这是必要的,你的函数是可能太长了

最干净的方法是:

B b;
doSomething(&b);

但是你真正应该写什么取决于doSomething函数做什么。如果在callingRoutine的末尾销毁b是可以的,那么这是更快更干净的方法,因为在堆栈上分配比new快,并且不需要在之后删除b

我有点惊讶居然没有人指出这个显而易见的事实:

void callingRoutine()
{
    doSomething(&B());
}

我不得不怀疑整个设计需要传入一个指针指向一个对象,但当它完成后,你显然忽略了它操作的对象,但如果你确定你想要什么,你正在做什么,这似乎是最简单,最直接的方式来实现它。

在您的情况下,您可以使用自动变量(堆栈上)

void callingRoutine()
{
  B obj;
  doSomething( &obj );
}  // obj is destroyed automatically

这没有给出警告。此外,只有当您确实希望在函数作用域之外长时间地引用/访问内存地址时,才应该使用new。在函数块中,用new分配是没有意义的。

请参考Bjarne页面上的链接,他在其中指出了与您的示例完全相同的示例。

顺便说一下,如果你只想要一行,那么解决方案将不干净,但这里有一个解决方案:

B obj; doSomething( &obj );

可能是下面的东西?

void doSomething( std::auto_ptr<A> _p ) { /** stuff */ }
void callingRoutine()
{
  doSomething(std::auto_ptr<A>(new B));
}

解决问题的最简单方法是按如下方式更改代码:

void callingRoutine()
{
    B temp;
    doSomething( &temp );
}

这是有效的,因为你只需要多态访问doSomething(),这是保证的事实,你传递一个指针到temp通过它的地址。

将指针传递给临时对象通常是一个坏主意,因为该对象可能在被调用者完成使用之前被销毁。在您的示例中,doSomething()应该在对象被删除或超出范围之前返回,因此,直到doSomething不存储对对象的任何引用之前,这都不是问题。

可以在调用或表达式期间将临时值(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()));
}