Применение unique_ptr
От: Аноним  
Дата: 12.03.14 06:06
Оценка:
Здравствуйте!
Расскажите пожалуйста про практическое применение unique_ptr. Не могу понять в каких случаях он нужен. Все примеры в инете абстрактные и демонститруют лишь свойства этого указателя, а не реальные задачи где без него не обойтись
Re: Применение unique_ptr
От: jazzer Россия Skype: enerjazzer
Дата: 12.03.14 06:18
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте!

А>Расскажите пожалуйста про практическое применение unique_ptr. Не могу понять в каких случаях он нужен. Все примеры в инете абстрактные и демонститруют лишь свойства этого указателя, а не реальные задачи где без него не обойтись

Он нужен, чтоб не звать delete руками.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Применение unique_ptr
От: Άнoним  
Дата: 12.03.14 07:23
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Он нужен, чтоб не звать delete руками.


Это понятно. shared_ptr тоже нужен чтобы не делать delete руками, но с ним понятно — что-то типа указателя со сборкой мусора на подсчете ссылок.
Меня интересуют практические, архитектурные области применения unique_ptr.
Re[3]: Применение unique_ptr
От: jazzer Россия Skype: enerjazzer
Дата: 12.03.14 07:33
Оценка:
Здравствуйте, Άнoним, Вы писали:

Ά>Здравствуйте, jazzer, Вы писали:


J>>Он нужен, чтоб не звать delete руками.


Ά>Это понятно. shared_ptr тоже нужен чтобы не делать delete руками, но с ним понятно — что-то типа указателя со сборкой мусора на подсчете ссылок.


Так из названия же видно.
shared_ptr — для совместного владения, когда на объект может указывать много shared_ptr (можно создавать копии) и объект убивают, только когда все ссылки помрут.
unique_ptr — уникален, т.е. нескольких unique_ptr, указывающих на один и тот же объект, быть не может (копирование запрещено). Но при этом разрешена передача владения от одного unique_ptr другому, с одновременным уничтожением первого.

Ά>Меня интересуют практические, архитектурные области применения unique_ptr.


Архитектурно — везде, где у тебя в программе есть владеющий указатель (т.е. по которому ты зовешь delete, когда он тебе больше не нужен) и он ровно один для каждого объекта, на который он указывает, имеет смысл вместо голого указателя использовать unique_ptr.
Еще один сценарий — функции-фабрики, возвращающие указатель на вновь созданный объект. Такой указатель тоже имеет смысл возвращать как unique_ptr — тогда он гарантировано помрет, даже если результат по какой-то причине не будет использован (например, из-за исключенияв неподходящий момент).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Применение unique_ptr
От: Chorkov Россия  
Дата: 12.03.14 08:05
Оценка: -1 :)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте!

А>Расскажите пожалуйста про практическое применение unique_ptr. Не могу понять в каких случаях он нужен. Все примеры в инете абстрактные и демонститруют лишь свойства этого указателя, а не реальные задачи где без него не обойтись


   // Пример 1: возврат объекта из фабрики
   std::unique_ptr<CriticleSectionLock> lock(CriticleSection& sec)
   {
       return std::unique_ptr<CriticleSectionLock>( new CriticleSectionLock(sec) );
   }

   void foo(
      Resource A, CriticleSection* protectA, // ресурс возможно защищен критической секцией, а может и нет.... 
      Resource B, CriticleSection* protectB)
   {
      std::unique_ptr<CriticleSectionLock> lockA, lockB;
      
      // Пример 2: условное создание объекта: 
      //  Не переменная на стеке потому что есть условие на создание.
      //  Не shared_ptr потому что не нужен его overhead.
      if(protectA)
         lockA = lock(*protectA);
      if(protectB && protectA!=protectB )
         lockB = lock(*protectB);

      // Что-то делаем с А и B.
   }
Re[2]: Применение unique_ptr
От: Abyx Россия  
Дата: 12.03.14 08:44
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте!

А>>Расскажите пожалуйста про практическое применение unique_ptr. Не могу понять в каких случаях он нужен. Все примеры в инете абстрактные и демонститруют лишь свойства этого указателя, а не реальные задачи где без него не обойтись


C>
C>   // Пример 1: возврат объекта из фабрики
C>   std::unique_ptr<CriticleSectionLock> lock(CriticleSection& sec)
C>   {
C>       return std::unique_ptr<CriticleSectionLock>( new CriticleSectionLock(sec) );
C>   }

C>   void foo(
C>      Resource A, CriticleSection* protectA, // ресурс возможно защищен критической секцией, а может и нет.... 
C>      Resource B, CriticleSection* protectB)
C>   {
C>      std::unique_ptr<CriticleSectionLock> lockA, lockB;
      
C>      // Пример 2: условное создание объекта: 
C>      //  Не переменная на стеке потому что есть условие на создание.
C>      //  Не shared_ptr потому что не нужен его overhead.
C>      if(protectA)
C>         lockA = lock(*protectA);
C>      if(protectB && protectA!=protectB )
C>         lockB = lock(*protectB);

C>      // Что-то делаем с А и B.
C>   }
C>


lol @ "Criticle"

вообще-то есть всякие std::mutex, std::*_lock

и если вместо них использовать unique_ptr, то new не нужен, нужен deleter

std::unique_ptr<CriticleSectionLock, void(*)(CriticleSection*)> lock(CriticleSection* sec)
{
    if (sec) sec->lock();
    return {sec, [](CriticleSection* sec){ if (sec) sec->unlock(); }};
}
In Zen We Trust
Re[3]: Применение unique_ptr
От: Stanislav V. Zudin Россия  
Дата: 12.03.14 09:10
Оценка:
Здравствуйте, Abyx, Вы писали:

ИМХО, конечно... но С++'11 читабельности не добавляет.

A>
A>std::unique_ptr<CriticleSectionLock, void(*)(CriticleSection*)> lock(CriticleSection* sec)
A>{
A>    if (sec) sec->lock();
A>    return {sec, [](CriticleSection* sec){ if (sec) sec->unlock(); }};
A>}
A>
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Применение unique_ptr
От: Abyx Россия  
Дата: 12.03.14 09:25
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, Abyx, Вы писали:


SVZ>ИМХО, конечно... но С++'11 читабельности не добавляет.


A>>
A>>std::unique_ptr<CriticleSectionLock, void(*)(CriticleSection*)> lock(CriticleSection* sec)
A>>{
A>>    if (sec) sec->lock();
A>>    return {sec, [](CriticleSection* sec){ if (sec) sec->unlock(); }};
A>>}
A>>


unique_ptr это и есть С++11
In Zen We Trust
Re[2]: Применение unique_ptr
От: Jack128  
Дата: 12.03.14 09:48
Оценка: +1
Здравствуйте, Chorkov, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте!

А>>Расскажите пожалуйста про практическое применение unique_ptr. Не могу понять в каких случаях он нужен. Все примеры в инете абстрактные и демонститруют лишь свойства этого указателя, а не реальные задачи где без него не обойтись


C>
C>   // Пример 1: возврат объекта из фабрики
C>   std::unique_ptr<CriticleSectionLock> lock(CriticleSection& sec)
C>   {
C>       return std::unique_ptr<CriticleSectionLock>( new CriticleSectionLock(sec) );
C>   }

C>   void foo(
C>      Resource A, CriticleSection* protectA, // ресурс возможно защищен критической секцией, а может и нет.... 
C>      Resource B, CriticleSection* protectB)
C>   {
C>      std::unique_ptr<CriticleSectionLock> lockA, lockB;
      
C>      // Пример 2: условное создание объекта: 
C>      //  Не переменная на стеке потому что есть условие на создание.
C>      //  Не shared_ptr потому что не нужен его overhead.
C>      if(protectA)
C>         lockA = lock(*protectA);
C>      if(protectB && protectA!=protectB )
C>         lockB = lock(*protectB);

C>      // Что-то делаем с А и B.
C>   }
C>


а зачем тут вообще "new" CriticleSectionLock ?? Почему бы просто CriticleSectionLock не вернуть? безо всяких указателей??
Re[4]: Применение unique_ptr
От: Άнoним  
Дата: 12.03.14 10:38
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Архитектурно — везде, где у тебя в программе есть владеющий указатель (т.е. по которому ты зовешь delete, когда он тебе больше не нужен) и он ровно один для каждого объекта, на который он указывает, имеет смысл вместо голого указателя использовать unique_ptr.


У меня практически везде "владеющие" указатели. Т.е. есть какой-то класс, в нем указатель на что-то другое, в конструкторе создается объект и в деструкторе удаляется. Никто больше его удалить не может. Но я вот чего не понимаю: этот unique_ptr можно только перемещать. Как же я в таком случае отдам адрес объекта, на который указывает unique_ptr, кому-то для каких-то действий, если его передавать как аргумент функции нельзя???

А если я его преобразую к обычному указателю и передам, то в чем тогда смысл уникальности?
Re[5]: Применение unique_ptr
От: rusted Беларусь  
Дата: 12.03.14 11:39
Оценка:
Здравствуйте, Άнoним, Вы писали:

Ά>У меня практически везде "владеющие" указатели. Т.е. есть какой-то класс, в нем указатель на что-то другое, в конструкторе создается объект и в деструкторе удаляется. Никто больше его удалить не может.


Но в процессе эволюции кода явное удаление в деструкторе может потерятся. Лишняя мелочь, слежение за которой можно возложить на компилятор.

Ά>Но я вот чего не понимаю: этот unique_ptr можно только перемещать. Как же я в таком случае отдам адрес объекта, на который указывает unique_ptr, кому-то для каких-то действий, если его передавать как аргумент функции нельзя???


Ά>А если я его преобразую к обычному указателю и передам, то в чем тогда смысл уникальности?


Если для владеющих указателей использовать raii обертки (unique для уникальных, shared для разделяемых и т.д.), то в коде не остается явных вызовов delete. И тогда можно для себя ввести правило, что голый указатель — он всегда не владеющий.
Re[5]: Применение unique_ptr
От: jazzer Россия Skype: enerjazzer
Дата: 12.03.14 15:08
Оценка:
Здравствуйте, Άнoним, Вы писали:

Ά>Здравствуйте, jazzer, Вы писали:


J>>Архитектурно — везде, где у тебя в программе есть владеющий указатель (т.е. по которому ты зовешь delete, когда он тебе больше не нужен) и он ровно один для каждого объекта, на который он указывает, имеет смысл вместо голого указателя использовать unique_ptr.


Ά>У меня практически везде "владеющие" указатели. Т.е. есть какой-то класс, в нем указатель на что-то другое, в конструкторе создается объект и в деструкторе удаляется. Никто больше его удалить не может.


Тогда unique_ptr — то, что надо.

Ά>Но я вот чего не понимаю: этот unique_ptr можно только перемещать. Как же я в таком случае отдам адрес объекта, на который указывает unique_ptr, кому-то для каких-то действий, если его передавать как аргумент функции нельзя???


Для каких действий? Связанных с владением/временем жизни (удаление, создание копий указателей и т.п.) или просто поменять данные/подергать методы?
Если первое — тогда у тебя что-то не так с архитектурной точки зрения.
Если второе — есть метод get(), который даст тебе голый указатель. Рулез в том, что этот вызов явный и локальный — то есть ничего никуда не утечет и все вызовы можно отследить.

Ά>А если я его преобразую к обычному указателю и передам, то в чем тогда смысл уникальности?


Такого преобразования нет. Есть метод get() — он возвращает невладеющий указатель. Уникальность владеющего указателя остается в силе. А тебе надо в программе гарантировать, что не будет невладеющих указателей к моменту смерти владеющего.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Применение unique_ptr
От: Άнoним  
Дата: 13.03.14 07:06
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Такого преобразования нет. Есть метод get() — он возвращает невладеющий указатель. Уникальность владеющего указателя остается в силе. А тебе надо в программе гарантировать, что не будет невладеющих указателей к моменту смерти владеющего.


Таким образом, если я правильно понял вас и rusted, все что делает уникальный указатель — это просто обеспечивает автоматическое удаление своего объекта, и предоставляет некоторую "защиту от дурака" в виде запрета копирования себя? Получение обычных указателей из unique_ptr — нормальная практика. Никакой защиты от того, что я вызову delete для полученного указателя, язык не предоставляет, а все основывается только на негласном соглашении "если нигде не использовать явно new/delete воообще, то все будет хорошо".
Я правильно понимаю?
Re[7]: Применение unique_ptr
От: jazzer Россия Skype: enerjazzer
Дата: 13.03.14 07:25
Оценка:
Здравствуйте, Άнoним, Вы писали:

Ά>Здравствуйте, jazzer, Вы писали:


J>>Такого преобразования нет. Есть метод get() — он возвращает невладеющий указатель. Уникальность владеющего указателя остается в силе. А тебе надо в программе гарантировать, что не будет невладеющих указателей к моменту смерти владеющего.


Ά>Таким образом, если я правильно понял вас и rusted, все что делает уникальный указатель — это просто обеспечивает автоматическое удаление своего объекта, и предоставляет некоторую "защиту от дурака" в виде запрета копирования себя? Получение обычных указателей из unique_ptr — нормальная практика. Никакой защиты от того, что я вызову delete для полученного указателя, язык не предоставляет, а все основывается только на негласном соглашении "если нигде не использовать явно new/delete воообще, то все будет хорошо".

Ά>Я правильно понимаю?

Да.
rusted все правильно сказал: "можно для себя ввести правило, что голый указатель — он всегда не владеющий."
Если у тебя код типа такого:
void f(int*);
void g() {
  std::unique<int> p = ...;
  f( p.get() );
}

то никаких проблем нет — голый указатель возник и изчез, его жизнь ограничена вызовом функции f( p.get() ).

Таким образом, остается только гарантировать, что никто не создает уникальные указатели из голых, если только не известно достоверно, что это свежесозданный объект и им никто больше не управляет (например, это верно для указателя, который возвращает new).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.