在这种情况下如何使用auto_ptr

时间:2014-11-19 11:49:14

标签: c++ memory-management auto-ptr

我有以下代码:

void do_something(Image *image)
{

    Image *smoothed = NULL;
    Image *processed = NULL;
    if (condition_met) {
        smoothed = smooth(image);
        processed = smoothed;
    }
    else {
        processed = image;
    }

    ...
    delete smoothed_image
}

我想知道我是否可以做以下事情,如果这是正确的方法。我对从auto_ptr对象设置另一个指针以及是否以某种方式改变所有权感到困惑。

void do_something(Image *image)
{
    auto_ptr<Image *> smoothed;
    Image *processed = NULL;

    if (condition_met) {
        smoothed = smooth(image); // This should own the pointer returned by smooth
        processed = smoothed; // Is this OK? processed is not an auto_ptr
    }
    else {
        processed = image;
    }

    ...
    // Destructor for the 'smoothed' variable should be called.
    // The 'image' variable is not deleted.
}

析构函数是否会按照我的意图调用,这是正确的方法吗?

1 个答案:

答案 0 :(得分:3)

要点几点。假设平滑函数的签名是

Image* smooth(Image*);

然后您的代码最低限度必须更改为

void do_something(Image *image)
{
    auto_ptr<Image> smoothed;
    Image *processed = NULL;

    if (condition_met) {
      smoothed.reset(smooth(image)); // This should own the pointer returned by smooth
      processed = smoothed.get(); // Maybe?  Depends on what you're doing
    }
    else {
      processed = image;
    }

在某些情况下,将原始指针从智能指针中拉出是合理的,就像上面的smoothed.get()所做的那样,但是您必须理解写入由平滑的指针将在函数结束时删除,即使您已使用原始指针执行了其他操作。这里没有足够的信息来确定这是否是一个问题,但它是一种气味。

std :: auto_ptr 现已弃用,以支持 std :: unique_ptr 。最重要的原因是auto_ptr的内容被移动的方式:

std::auto_ptr<int> a = new int(5);
std::auto_ptr<int> b = a;  // Copy?  No!

在此代码中,a所持有的指针已转移到b。 a 不再持有任何东西。这与我们通常认为的复制行为方式背道而驰,因此很容易搞砸。

C ++ 11引入了r值引用的概念(网络上有大量文章解释了这一点,包括What are move semantics?)。拥有r值引用允许 unique_ptr 阻止数据移动到没有意义的地方。

std::unique_ptr<int> a = new(5);
std::unique_ptr<int> b = a; // Compile fail.  Not copyable
std::unique_ptr<int> c = std::move(a); // OK, shows intent

有了这个,就可以将smooth()函数签名更新为

std::unique_ptr<Image> smooth(Image*) {
  ...
  return newImage;
}

这清楚地指示调用者他们应该获得返回指针的所有权。现在你可以说

unique_ptr<Image> smoothed;
...
smoothed = smooth(image);

因为从函数返回的值是r值(尚未绑定到变量),指针会安全地移动到平滑

最后,是的,使用智能指针比调用删除更可取。只需仔细考虑您的设计,并尝试清楚指针所有权。