Чем boost::optional лучше чем NULL?
От: Аноним  
Дата: 07.08.14 13:09
Оценка:
Смотрю тут один код, повсеместно для указателей, которые могут указывать на объект, а могут не указывать никуда, применен boost::optional. Скажите, а чем такой подход лучше чем просто хранение NULL в указателе, если в данный момент он ни на что не указывает? Ведь проверять-то все равно надо, когда необходимо получить оттуда сам объект.
Re: Чем boost::optional лучше чем NULL?
От: jazzer Россия Skype: enerjazzer
Дата: 07.08.14 14:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Смотрю тут один код, повсеместно для указателей, которые могут указывать на объект, а могут не указывать никуда, применен boost::optional. Скажите, а чем такой подход лучше чем просто хранение NULL в указателе, если в данный момент он ни на что не указывает? Ведь проверять-то все равно надо, когда необходимо получить оттуда сам объект.


boost::optional хранит объект внутри себя, а не в куче, как указатель.
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]: Чем boost::optional лучше чем NULL?
От: zaufi Земля  
Дата: 07.08.14 17:49
Оценка: +1
Здравствуйте, jazzer, Вы писали:

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


А>>Смотрю тут один код, повсеместно для указателей, которые могут указывать на объект, а могут не указывать никуда, применен boost::optional. Скажите, а чем такой подход лучше чем просто хранение NULL в указателе, если в данный момент он ни на что не указывает? Ведь проверять-то все равно надо, когда необходимо получить оттуда сам объект.


J>boost::optional хранит объект внутри себя, а не в куче, как указатель.


из плюсов я бы назвал в первую очередь понятность кода (семантику). например, глядя на это:
some* get_some();
boost::optional<some> get_other_some();


не очень очевидно, что может вернуть `get_some()`, в то время как глядя на `get_other_some()` сразу понятно, что возвращает значения он не всегда.
еще больше информации можно получить если правильно назвать эти функции... например так: `try_get_some()`. в этом случае имя как бы намекает, что get может и не получиться... остается за кадром, что будет если таки не получится: исключение (этого тут вообще не видно) или nullptr в качестве результата.
Re: Чем boost::optional лучше чем NULL?
От: Igore Россия  
Дата: 07.08.14 18:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Смотрю тут один код, повсеместно для указателей, которые могут указывать на объект, а могут не указывать никуда, применен boost::optional. Скажите, а чем такой подход лучше чем просто хранение NULL в указателе, если в данный момент он ни на что не указывает? Ведь проверять-то все равно надо, когда необходимо получить оттуда сам объект.


Я думаю дело вкуса.
Имеем T* vs optional< T* >
T*
+ легко обращаться к объекту
— нужно не забывать инициализировать.
optional< T* > val
— громозкий доступ val.get()->some,
+ само инициализируется
+ вариант что нужно на самом деле различать отсутствие объекта, и нулевой объект
if( !val )
{}
else if( !val.get() )
{}
else
{}
Re[2]: Чем boost::optional лучше чем NULL?
От: flаt  
Дата: 07.08.14 19:14
Оценка: +1
Здравствуйте, Igore, Вы писали:

I>optional< T* > val


Не совсем корректно сравнивать T* и optional<T*>, который по семантике уже как T**.
Re: Чем boost::optional лучше чем NULL?
От: andrey.desman  
Дата: 07.08.14 19:24
Оценка: -1
Здравствуйте, Аноним, Вы писали:

А>Смотрю тут один код, повсеместно для указателей, которые могут указывать на объект, а могут не указывать никуда, применен boost::optional. Скажите, а чем такой подход лучше чем просто хранение NULL в указателе, если в данный момент он ни на что не указывает? Ведь проверять-то все равно надо, когда необходимо получить оттуда сам объект.



boost::optional<T>, или boost::optional<T*>

В первом случае имеем объект, или не имеем объект.

Во втором случае имеем указатель (который указывает на объект, или на его отсутствие), или не имеем указателя вообще. Это отличается от просто указателя, очевидно.

Так-то телепатов нет, пример давай. Может по делу, а может из-за недопонимания.
Re[3]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 07.08.14 21:13
Оценка: -2 :))
Здравствуйте, zaufi, Вы писали:

Z>из плюсов я бы назвал в первую очередь понятность кода (семантику). например, глядя на это:

Z>
Z>some* get_some();
Z>boost::optional<some> get_other_some();
Z>


Z>не очень очевидно, что может вернуть `get_some()`, в то время как глядя на `get_other_some()` сразу понятно, что возвращает значения он не всегда.


Вкусовщина. Лично мне очевидно, что если в качестве возвращаемого значения задан указатель, то он может быть и нулевым, если, конечно, в документации специально не оговорено иное. С другой стороны, насколько я помню (смотреть лень, да-с) "пустой" boost::optional при попытке разыменовать его гарантированно выкинет исключение, а вот разыменование нулевого указателя — формально, UB. Правда, насколько мне известно, на любой платформе, где существует бюст, разыменование нулевого указателя дает ошибку доступа к памяти и завершение приложения.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[3]: Чем boost::optional лучше чем NULL?
От: Igore Россия  
Дата: 08.08.14 05:01
Оценка:
Здравствуйте, flаt, Вы писали:

F>Не совсем корректно сравнивать T* и optional<T*>, который по семантике уже как T**.

Да, чего то я не то вечером написал , тогда остается
T* vs optional< T >
T*
— нужно не забывать инициализировать.
optional< T >
+ само инициализируется
Re[4]: Чем boost::optional лучше чем NULL?
От: Igore Россия  
Дата: 08.08.14 06:11
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Вкусовщина. Лично мне очевидно, что если в качестве возвращаемого значения задан указатель, то он может быть и нулевым, если, конечно, в документации специально не оговорено иное. С другой стороны, насколько я помню (смотреть лень, да-с) "пустой" boost::optional при попытке разыменовать его гарантированно выкинет исключение, а вот разыменование нулевого указателя — формально, UB. Правда, насколько мне известно, на любой платформе, где существует бюст, разыменование нулевого указателя дает ошибку доступа к памяти и завершение приложения.


Нет там исключения, но асерт помогает.
// Returns a reference to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
Re[5]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 08.08.14 07:57
Оценка:
Здравствуйте, Igore, Вы писали:

I>Нет там исключения

Зря я, конечно, поленился посмотреть. Но вообще странно — бюст, да вдруг без исключения обошлись? Это они недоработали

I>
I>// Returns a reference to the value if this is initialized, otherwise,
I>// the behaviour is UNDEFINED
I>// No-throw
I>reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
I>


Ну вот как бы что assert при попытке получить несуществующее значение, что segmentation fault при попытке разыменовать нулевой "голый" указатель — хрен перца не слаще.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[6]: Чем boost::optional лучше чем NULL?
От: DarkEld3r  
Дата: 08.08.14 08:31
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Но вообще странно — бюст, да вдруг без исключения обошлись? Это они недоработали

По моему, вполне согласовывается с остальными бустовыми библиотеками. В смысле, есть возможность проверить присутствует значение или нет. И есть доступ без "дополнительных издержек".
Re[4]: Чем boost::optional лучше чем NULL?
От: Abyx Россия  
Дата: 08.08.14 12:37
Оценка: -1
Здравствуйте, slava_phirsov, Вы писали:

_>разыменование нулевого указателя — формально, UB. Правда, насколько мне известно, на любой платформе, где существует бюст, разыменование нулевого указателя дает ошибку доступа к памяти и завершение приложения.


во-первых это фактически UB. т.е. компилятор может оптимизировать код исходя из допущений что при разыменовении указатель не пустой.
во-вторых на x86 разыменование нулевого указателя приводит к аппаратному исключению, и некоторые ОС/компиляторы позволяют его перехватить и обработать.
In Zen We Trust
Re[5]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 08.08.14 12:54
Оценка:
Здравствуйте, Abyx, Вы писали:


A>во-первых это фактически UB. т.е. компилятор может оптимизировать код исходя из допущений что при разыменовении указатель не пустой.


Пример такой оптимизации?

A>во-вторых на x86 разыменование нулевого указателя приводит к аппаратному исключению, и некоторые ОС/компиляторы позволяют его перехватить и обработать.


Почему-то даже не хочется вспоминать кэпа. Позволяет перехватить и обработать — и что? Старый добрый, сто раз заданный вопрос: перехватили, как обрабатывать будем? Вот, для определенности, под *nix перехвачен сигнал SEGV: что делаем (с примером кода)?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[6]: Чем boost::optional лучше чем NULL?
От: Abyx Россия  
Дата: 08.08.14 13:42
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

A>>во-первых это фактически UB. т.е. компилятор может оптимизировать код исходя из допущений что при разыменовении указатель не пустой.


_>Пример такой оптимизации?


http://coliru.stacked-crooked.com/a/88872e0375f755f0

A>>во-вторых на x86 разыменование нулевого указателя приводит к аппаратному исключению, и некоторые ОС/компиляторы позволяют его перехватить и обработать.


_>Почему-то даже не хочется вспоминать кэпа. Позволяет перехватить и обработать — и что? Старый добрый, сто раз заданный вопрос: перехватили, как обрабатывать будем? Вот, для определенности, под *nix перехвачен сигнал SEGV: что делаем (с примером кода)?


я хз что за сигналы у вас в никсах, но в винде можно написать

for (;;) {
  __try {
    f();
  } __except (log_exception()) {}
}


и это будет вполне нормально работать.
я видел игровой сервер со средним аптаймом около месяца,
там был похожий код, несколько раз в месяц там ловились #AV, но все прекрасно работало — никакие данные не терялись.
In Zen We Trust
Re[7]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 08.08.14 14:07
Оценка:
Здравствуйте, Abyx, Вы писали:

A>http://coliru.stacked-crooked.com/a/88872e0375f755f0


многабукаф можешь тезисно изложить? Своими словами. Не могу вкурить, честно.


A>я хз что за сигналы у вас в никсах


Собственно с этого надо было начинать


A>но в винде можно написать


A>
A>for (;;) {
A>  __try {
A>    f();
A>  } __except (log_exception()) {}
A>}
A>


A>и это будет вполне нормально работать.

A>я видел игровой сервер со средним аптаймом около месяца,
A>там был похожий код, несколько раз в месяц там ловились #AV, но все прекрасно работало — никакие данные не терялись.

Что мешало сделать приложение службой, которая тупо вылетает по Segmentation Fault, а затем перезапускается? Желание похвастаться, что оно крутится целый месяц до перезапуска?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[8]: Чем boost::optional лучше чем NULL?
От: Abyx Россия  
Дата: 08.08.14 14:13
Оценка: +3
Здравствуйте, slava_phirsov, Вы писали:

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


A>>http://coliru.stacked-crooked.com/a/88872e0375f755f0


_>многабукаф можешь тезисно изложить? Своими словами. Не могу вкурить, честно.


что непонятно-то? там есть код
if (!p) return never_called_function(); // dead code, shall be eliminated

и он мертвый, компилятор его выкидывает потому что перед ним написано *p

_>Что мешало сделать приложение службой, которая тупо вылетает по Segmentation Fault, а затем перезапускается? Желание похвастаться, что оно крутится целый месяц до перезапуска?

то что при падении приложения теряются все данные в RAM?
то что при вызове terminate не вызываются деструкторы? "раскрутка стека" — может слышал что-то?
In Zen We Trust
Re[9]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 08.08.14 14:35
Оценка: -5
Здравствуйте, Abyx, Вы писали:

A>что непонятно-то? там есть код

A>
A>if (!p) return never_called_function(); // dead code, shall be eliminated
A>

A>и он мертвый, компилятор его выкидывает потому что перед ним написано *p


Собственно к природе указателей это имеет слабое отношение. С таким же успехом компилятор будет оптимизировать такое:

inline void foo(int bar)
{
    if (!bar)
        baz();
}

foo(1); // скорее всего соптимизируется до пустого места



A>то что при падении приложения теряются все данные в RAM?

Точно так же они потеряются если уборщица шнур питания шваброй выдернет. Проблема целостности данных решается совсем другими методами.

A>то что при вызове terminate не вызываются деструкторы?

Зачем тебе при завершении приложения вызов деструкторов?

A>"раскрутка стека" — может слышал что-то?

Без комментариев.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[9]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 08.08.14 14:46
Оценка:
Здравствуйте, Abyx, Вы писали:

_>>Что мешало сделать приложение службой, которая тупо вылетает по Segmentation Fault, а затем перезапускается? Желание похвастаться, что оно крутится целый месяц до перезапуска?

A>то что при падении приложения теряются все данные в RAM?
A>то что при вызове terminate не вызываются деструкторы? "раскрутка стека" — может слышал что-то?


Рекомендую по этому поводу почитать Спинеллиса, "Идеальная архитектура" — там на примере игровой инфраструктуры Darkstar описывается, как нужно решать подобные задачи.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[10]: Чем boost::optional лучше чем NULL?
От: Abyx Россия  
Дата: 08.08.14 16:24
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>>>Что мешало сделать приложение службой, которая тупо вылетает по Segmentation Fault, а затем перезапускается? Желание похвастаться, что оно крутится целый месяц до перезапуска?

A>>то что при падении приложения теряются все данные в RAM?
A>>то что при вызове terminate не вызываются деструкторы? "раскрутка стека" — может слышал что-то?

_>Рекомендую по этому поводу почитать Спинеллиса, "Идеальная архитектура" — там на примере игровой инфраструктуры Darkstar описывается, как нужно решать подобные задачи.


я в курсе как решать эти задачи.
я просто привел пример того как обработка #AV успешно работала в реальном проекте (который писался в начале нулевых и не мной)
In Zen We Trust
Re[10]: Чем boost::optional лучше чем NULL?
От: alzt  
Дата: 12.08.14 19:51
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>>>Что мешало сделать приложение службой, которая тупо вылетает по Segmentation Fault, а затем перезапускается? Желание похвастаться, что оно крутится целый месяц до перезапуска?

A>>то что при падении приложения теряются все данные в RAM?
A>>то что при вызове terminate не вызываются деструкторы? "раскрутка стека" — может слышал что-то?


_>Рекомендую по этому поводу почитать Спинеллиса, "Идеальная архитектура" — там на примере игровой инфраструктуры Darkstar описывается, как нужно решать подобные задачи.


UB означает, что компилятор может оптимизировать код по своему усмотрению. И он будет по максимуму оптимизировать.
Re[4]: Чем boost::optional лучше чем NULL?
От: alzt  
Дата: 12.08.14 19:52
Оценка: +1
Здравствуйте, slava_phirsov, Вы писали:

Z>>из плюсов я бы назвал в первую очередь понятность кода (семантику). например, глядя на это:

Z>>
Z>>some* get_some();
Z>>boost::optional<some> get_other_some();
Z>>


Z>>не очень очевидно, что может вернуть `get_some()`, в то время как глядя на `get_other_some()` сразу понятно, что возвращает значения он не всегда.


_>Вкусовщина. Лично мне очевидно, что если в качестве возвращаемого значения задан указатель, то он может быть и нулевым, если, конечно, в документации специально не оговорено иное. С другой стороны, насколько я помню (смотреть лень, да-с) "пустой" boost::optional при попытке разыменовать его гарантированно выкинет исключение, а вот разыменование нулевого указателя — формально, UB. Правда, насколько мне известно, на любой платформе, где существует бюст, разыменование нулевого указателя дает ошибку доступа к памяти и завершение приложения.


Люди не любят проверять возвращаемое значение и часто это делают. Пример, функция malloc, её результат очень часто забывают проверить.
А вот с optional такое уже не прокатит.
Re[5]: Чем boost::optional лучше чем NULL?
От: slava_phirsov Россия  
Дата: 12.08.14 21:52
Оценка:
Здравствуйте, alzt, Вы писали:

A>Люди не любят проверять возвращаемое значение и часто это делают. Пример, функция malloc, её результат очень часто забывают проверить.

A>А вот с optional такое уже не прокатит.

Как тут где-то выше говорилось, если malloc вернет тебе NULL, а ты, не глядя, попытаешься его разыменовать, на PC ты получишь ошибку сегментации и приложение тупо вылетит. Если не проверишь optional — получишь вылет по BOOST_ASSERT. Разница? Вообще-то никакой.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re: Чем boost::optional лучше чем NULL?
От: antropolog  
Дата: 13.08.14 08:07
Оценка: +1 -1
Здравствуйте, Аноним, Вы писали:

А>Смотрю тут один код, повсеместно для указателей, которые могут указывать на объект, а могут не указывать никуда, применен boost::optional. Скажите, а чем такой подход лучше чем просто хранение NULL в указателе, если в данный момент он ни на что не указывает? Ведь проверять-то все равно надо, когда необходимо получить оттуда сам объект.


Лучше тем что явно выражает намерение. Как я могу узнать глядя на сигнатуру метода, что возвращаемый указатель может быть NULL и это валидное поведение (т.е. мне нужно писать if( ptr ) а не assert( ptr )? Только заглянув в имплементацию. boost::optional позволяет избежать этих лишних телодвижений и явно говорит о том что пустое возвращаемое значение не является нарушением инварианта.
Re[2]: Чем boost::optional лучше чем NULL?
От: Кодт Россия  
Дата: 13.08.14 14:40
Оценка:
Здравствуйте, antropolog, Вы писали:

A>Лучше тем что явно выражает намерение. Как я могу узнать глядя на сигнатуру метода, что возвращаемый указатель может быть NULL и это валидное поведение (т.е. мне нужно писать if( ptr ) а не assert( ptr )? Только заглянув в имплементацию. boost::optional позволяет избежать этих лишних телодвижений и явно говорит о том что пустое возвращаемое значение не является нарушением инварианта.


И ещё тем, что не предполагает полиморфизм, и предполагает монопольное/эстафетное владение
Some* foo()
{
  ... return new Some() ...
  ... return new Derived() ...
  ... return &g_some ...
  ... return &g_derived ...
  ... return nullptr ...
}

optional<Some> bar()
{
  ... return Some() ...
  ... return nullopt ...
}
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.