2014-11-19 2 views
1

У меня есть следующий код:Как использовать 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. 
} 

Будет ли деструктор вызван, как я его намерен, и это правильный способ сделать это?

+5

должно быть 'auto_ptr сглажено;' и вы должны, вероятно, использовать 'smoothed.reset (new_value);' установить и 'smoothed.get()', чтобы получить указатель, принадлежащий 'auto_ptr'. Кроме того, 'auto_ptr' больше не нужно использовать, если это вообще возможно, если вы можете использовать' unique_ptr' вместо этого. – PeterT

+2

@Luca Где объявлено smoothed_image? –

+0

@PeterT зачем писать ответ в виде комментария? – Kos

ответ

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() выше, но вы должны понимать, что, как написано, указатель, удерживаемый , сглаженный будет удален в конце функции, даже если вы сделали что-то еще с необработанным указателем. Недостаточно информации здесь, чтобы узнать, есть ли проблема, но это запах.

станд :: auto_ptr теперь осуждается в пользу станд :: unique_ptr. Большая причина для этого является способом содержимого auto_ptr перемещается:

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

В этом коде указатель удерживается перенесенным в б. a больше не держит ничего. Это противоречит тому, как мы обычно думаем о работе с копией, поэтому ее легко испортить.

C++ 11 представил концепцию ссылок на r-значение (это объясняет это множество статей по сети, включая What are move semantics?). Наличие ссылок r-value позволяет 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 

При этом в наличии, можно было бы обновить плавную() функция подписи

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

Что явно инструктирует абонента о том, что они должны взять на себя ответственность по возвращенного указателя. Теперь вы можете сказать

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

Поскольку значение, возвращаемое функцией является г-значение (не связан с переменной пока), указатель благополучно переехал в сглажены.

В конце концов, да, используя смарт-указатель, предпочтительнее позвонить удалить. Просто продумайте свой дизайн и постарайтесь понять, что такое владение указателем.

+0

Как насчет ссылки на запись [C++ - faq] в [перемещение семантики здесь на SO] (http://stackoverflow.com/q/3106110/256138)? – rubenvb

+0

@rubenvb добавлен, спасибо –