我有以下代码:
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.
}
析构函数是否会按照我的意图调用,这是正确的方法吗?
答案 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值(尚未绑定到变量),指针会安全地移动到平滑。
最后,是的,使用智能指针比调用删除更可取。只需仔细考虑您的设计,并尝试清楚指针所有权。