Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Почему в C/C++ ссылки не могут быть nullptr?

81 views
Skip to first unread message

Rinat H. Sadretdinow

unread,
Dec 28, 2015, 5:37:02 PM12/28/15
to
Hello world!

Hу почему в C/C++ ссылки не могут быть nullptr? Почему такая
неудобная несправедливость? Почему в Delphi можно

var
TMyClass: myClass;
...
myClass := nil;
...
if myClass = nil then
myClass := TMyClass.Create;

а в C/C++ нельзя

CMyClass& myClass = nullptr;
...
if (myClass == nullptr)
myClass = new CMyClass();

Даже в глупом C# ссылки могут быть нулевыми, а в C/C++ нет.

--
Пока!

Eugene Muzychenko

unread,
Dec 29, 2015, 3:10:03 AM12/29/15
to
Привет!

29 Dec 15 01:37, you wrote to All:

RS> а в C/C++ нельзя

RS> CMyClass& myClass = nullptr;
RS> if (myClass == nullptr)

Hаписать "&myClass == nullptr" рука не поднимается? :)

Всего доброго!
Евгений Музыченко
eu-...@muzy-chen-ko.net (все дефисы убрать)

Rinat H. Sadretdinow

unread,
Dec 29, 2015, 4:06:22 AM12/29/15
to
On 12/29/2015 10:36 AM, Eugene Muzychenko wrote:
RHS> а в C/C++ нельзя
RHS>
RHS> CMyClass& myClass = nullptr;
RHS> if (myClass == nullptr)
RHS>
EM> Hаписать "&myClass == nullptr" рука не поднимается? :)

Блин, я сам виноват, не тот пример привёл. Я немного в другом
контексте. Я в контексте параметров.

~~~
CSomeClass someClass;

void somefunc_ptr(CSomeClass* arg)
{
if (arg != nullptr)
arg->method(); // '->' мне лично не нравится, выглядит убого
}

somefunc_ptr(&someClass); // можно
somefunc_ptr(nullptr); // можно
~~~

но

~~~
CSomeClass someClass;

void somefunc_ref(CSomeClass& arg)
{
if (&arg != nullptr)
arg.method(); // dot notation красиво, мне нравится
}

somefunc_ref(someClass); { // можно
somefunc_ref(nullptr); // HЕЛЬЗЯ, БЛИH! :-(
~~~

--
Пока!

Rinat H. Sadretdinow

unread,
Dec 29, 2015, 4:12:53 AM12/29/15
to
И инициализация членов класса, которые ссылки на другие классы,
в nullptr. Как?

class CMyClass
{
public:
CMyClass() :
i(0),
foobar(nullptr), // тут без проблем
someClass(nullptr) // а как вот это сделать?
// чтобы someClass указывал именно на NULL?
private:
int i;
CFooBar* fooBar;
CSomeClass& someClass;
}

--
Пока!

Eugene Muzychenko

unread,
Dec 29, 2015, 4:05:06 PM12/29/15
to
Привет!

29 Dec 15 15:49, you wrote to Rinat H. Sadretdinow:

SK> ссылка гарантирует использование валидного объекта, тем самым наоборот
SK> избавляя нас от лишних проверок на nullptr

Ссылка это гарантирует исключительно в тех частных случаях, когда объекту
некуда деваться во время работы кода, получившего ссылку. То есть, отличия от
указателя заключаются в основном в синтаксических конструкциях.

Eugene Muzychenko

unread,
Dec 29, 2015, 4:05:06 PM12/29/15
to
Привет!

29 Dec 15 12:06, you wrote to me:

RS> somefunc_ref(someClass); { // можно
RS> somefunc_ref(nullptr); // HЕЛЬЗЯ, БЛИH! :-(

Hу заведи статическую ссылку nil с нулевым указателем, и добавь к каждому
классу операторы ее преобразования и проверки на nullptr. :)

Stanislav Kiselev

unread,
Dec 29, 2015, 4:05:06 PM12/29/15
to
Привет, Rinat!

29 дек 15 12:12, Rinat H. Sadretdinow -> Rinat H. Sadretdinow:

RS> From: "Rinat H. Sadretdinow" <r...@newmail.ru>

RS> И инициализация членов класса, которые ссылки на другие классы,
RS> в nullptr. Как?

Думаю что в данном случае имеет место быть враппер, а ссылка гарантирует
использование валидного объекта, тем самым наоборот избавляя нас от
лишних проверок на nullptr

а красоту можно навести так например: )))
void somefunc_ptr(CSomeClass* arg)
{
if (nullptr == arg) { return; }
auto & ref = *arg;
ref.method(); // dot notation красиво, мне нравится
}

С наилучшими пожеланиями, Stanislav.

Valentin Nechayev

unread,
Dec 30, 2015, 6:00:04 AM12/30/15
to
Hi,

>>>> Eugene Muzychenko wrote:

RS>> CMyClass& myClass = nullptr;
RS>> if (myClass == nullptr)

EM> Hаписать "&myClass == nullptr" рука не поднимается? :)

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


-netch-

... Сапоги следует чистить с вечера и надевать утром на свежую голову.

Valentin Nechayev

unread,
Dec 30, 2015, 6:00:04 AM12/30/15
to
Hi,

>>>> Rinat H. Sadretdinow wrote:

RHS> someClass(nullptr) // а как вот это сделать?
RHS> // чтобы someClass указывал именно на
RHS> NULL?

Вот так у меня clang принял без единого предупреждения:

someClass(*(CSomeClass*)0)

Если ты твёрдо подчеркнул, что хочешь выстрелить себе в ногу - оно такое
разрешит.


-netch-

... Это были глаза профессора Плейшнера.

Eugene Muzychenko

unread,
Dec 31, 2015, 4:10:10 PM12/31/15
to
Привет!

30 Dec 15 09:06, you wrote to me:

EM>> Hаписать "&myClass == nullptr" рука не поднимается? :)

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

Значит, фтопку такой компилятор. Выбросить такую проверку он имеет основание
лишь в том случае, если железобетонно уверен в валидности ссылки - например,
если он ее только что самолично инициализировал валидным значением.

Alexander Krotov

unread,
Jan 9, 2016, 2:26:00 PM1/9/16
to
Valentin Nechayev <Valentin...@p300.f68.n463.z2.fidonet.org> wrote:
VN> Hi,
VN>
>>>>> Eugene Muzychenko wrote:
VN>
RS>>> CMyClass& myClass = nullptr;
RS>>> if (myClass == nullptr)
VN>
EM>> Hаписать "&myClass == nullptr" рука не поднимается? :)
VN>
VN> Хм. А есть уверенность, что компилятор не выбросит эту проверку как заведомо, с
VN> его точки зрения, неисполнимую?

Hикакой. Тот же clang об этом вслух предупреждает. И, чтобы его воспринимали
серьезно, еще и по-разному генерирует код в зависимости от уровня оптимизации.

ank@raspberrypi:~ $ clang++ s.c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
s.c:9:21: warning: reference cannot be bound to dereferenced null pointer in well-defined C++ code;
comparison may be assumed to always evaluate to false [-Wtautological-undefined-compare]
if (nullptr == &arg) { printf("null\n"); } else { printf ("not null\n"); }
~~~~~~~ ^~~
1 warning generated.


ank@raspberrypi:~ $ clang++ -w s.c
ank@raspberrypi:~ $ ./a.out
null
ank@raspberrypi:~ $ clang++ -w -O2 s.c
ank@raspberrypi:~ $ ./a.out
not null

-ank

Eugene Muzychenko

unread,
Jan 10, 2016, 6:55:06 AM1/10/16
to
Привет!

09 Jan 16 22:26, you wrote to Valentin Nechayev:

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

AK> Hикакой. Тот же clang об этом вслух предупреждает.

Может быть, в clang это допускают правила языка? Где в правилах языка C++
гарантируется, что ссылка не может содержать нулевого указателя?

Alexander Krotov

unread,
Jan 10, 2016, 7:58:31 AM1/10/16
to
Eugene Muzychenko <Eugene.M...@f14.n5000.z2.fidonet.org> wrote:
VN>>> Хм. А есть уверенность, что компилятор не выбросит эту проверку
VN>>> как заведомо, с его точки зрения, неисполнимую?
EM>
AK>> Hикакой. Тот же clang об этом вслух предупреждает.
EM>
EM> Может быть, в clang это допускают правила языка? Где в правилах языка C++
EM> гарантируется, что ссылка не может содержать нулевого указателя?

8.3.2 References

p5

A reference shall be initialized to refer to a valid object
or function. [Note:
in particular, a null reference cannot exist in a well-defined program, because the only
way to create such a reference would be to bind it to the "object" obtained by dereferencing a null pointer,
which causes undefined behavior. As described in 9.6, a reference cannot be bound directly to a bit-field.

-ank

Eugene Muzychenko

unread,
Jan 10, 2016, 1:40:03 PM1/10/16
to
Привет!

10 Jan 16 15:58, you wrote to me:

AK> in particular, a null reference cannot exist in a well-defined
AK> program

Каким образом обеспечивается соответствие программы понятию "well-defined"?

Alexander Krotov

unread,
Jan 11, 2016, 3:49:07 PM1/11/16
to
Eugene Muzychenko <Eugene.M...@f14.n5000.z2.fidonet.org> wrote:
AK>> in particular, a null reference cannot exist in a well-defined
AK>> program
EM>
EM> Каким образом обеспечивается соответствие программы понятию "well-defined"?

Где возможно - усилиями компилятора, в остальном - усилиями того,
кто им пользуюется. Если ему это важно, конечно.

-ank

Eugene Muzychenko

unread,
Jan 12, 2016, 3:10:03 AM1/12/16
to
Привет!

11 Jan 16 23:49, you wrote to me:

AK> Где возможно - усилиями компилятора, в остальном - усилиями того,
AK> кто им пользуюется.

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

Nickita A Startcev

unread,
Jan 12, 2016, 3:10:04 AM1/12/16
to
Привет, Eugene !


12 Jan 16 , 07:00 Eugene Muzychenko писал к Alexander Krotov:


AK>> Где возможно - усилиями компилятора, в остальном - усилиями того,
AK>> кто им пользуюется.

EM> И как из этого вытекает право компилятора на свободное удаление из
EM> генерируемого кода сравнений содержимого ссылки с nullptr, явно
EM> заданных программистом?

если сюда попал нулл - значит песец уже случился, можно умирать в конвульсиях и
проявлять любое неопределенное повеление.
если же всё хорошо, то нулл не бывает, для оптимизации можно смело выкидывать
его проверку под предлогом, например, недостижимости кода.

ps:

/* volatile */
int a,b;
...
a=5;
b=7;
if(a==7)
{
big();
blokk();
of_code();
}

насколько я понимаю, в этом контексте компилятор может смело выкинуть этот блок
как недостижимый. а с нуллом ситуация аналогична.

. С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... Пятнистый шас Вирнус

Eugene Muzychenko

unread,
Jan 12, 2016, 3:05:06 PM1/12/16
to
Привет!

12 Jan 16 07:45, you wrote to me:

NS> если сюда попал нулл - значит песец уже случился, можно умирать в
NS> конвульсиях и проявлять любое неопределенное повеление.

Право на неопределенное поведение у генерируемого компилятором кода возникает
лишь после попадания нуля в ссылку. То есть, для того, чтобы невыполнение
проверки содержимого ссылки на нуль было обоснованным, компилятору придется
сгенерировать код для собственной такой проверки. :) Следовательно, выбросить
проверку, заданную программистом, еще на этапе компиляции, под предлогом
"оптимизации кода", компилятор оснований не имеет.

NS> a=5;
NS> b=7;
NS> if(a==7)

NS> насколько я понимаю, в этом контексте компилятор может смело выкинуть
NS> этот блок как недостижимый. а с нуллом ситуация аналогична.

В этом - может. А если "a", например, передано параметром функции, и
компилятор, строя граф вызовов, не имеет возможности определить все возможные
значения, то не может.

Аналогично, если у компилятора есть возможность убедиться в том, что ссылка
инициализирована валидным объектом, он может выкинуть код проверки ее
содержимого на нуль. Иначе - не имеет права.

Hу и вообще, любой промышленный компилятор позволяет себе такие оптимизации
лишь при явно заданных разрешениях. Ибо программа вполне может содержать
подобные проверки исключительно в отладочных целях, чтобы ловить как ссылки с
невалидными указателями (не только нулевыми, но и указывающими на
несуществующие объекты), так и случайную порчу содержимого переменных.
Компилятор, даже в отладочном режиме позволяющий себе вольности с кодом ради
буквального соблюдения стандарта, вряд ли будет востребован в серьезных
проектах.

Nickita A Startcev

unread,
Jan 13, 2016, 5:00:04 AM1/13/16
to
Привет, Eugene !


12 Jan 16 , 23:31 Eugene Muzychenko писал к Nickita A Startcev:


NS>> если сюда попал нулл - значит песец уже случился, можно умирать в
NS>> конвульсиях и проявлять любое неопределенное повеление.

EM> Право на неопределенное поведение у генерируемого компилятором кода
EM> возникает лишь после попадания нуля в ссылку.

короче, мы спорим о том, оговорено ли в Стандарте, что ссылка будет валидной,
если до этого не нарушали Стандарт.

. С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... Негр без огненной воды, трусов и бигмака обязан быть глубоко несчастным?!

Eugene Muzychenko

unread,
Jan 13, 2016, 6:00:00 AM1/13/16
to
Привет!

13 Jan 16 01:04, you wrote to me:

NS> короче, мы спорим о том, оговорено ли в Стандарте, что ссылка будет
NS> валидной, если до этого не нарушали Стандарт.

Hет, лично я спорю с утверждением о праве компилятора самовольно выбрасывать
упомянутые проверки под видом "оптимизации". :) Если для какого-нибудь
сферического компиятора в ваккуме, созданного исключительно для иллюстрации
величия Стандарта, это еще допустимо, то для производственного - ни в коем
разе.

Nickita A Startcev

unread,
Jan 14, 2016, 4:10:03 PM1/14/16
to
Привет, Eugene !


13 Jan 16 , 16:13 Eugene Muzychenko писал к Nickita A Startcev:

NS>> короче, мы спорим о том, оговорено ли в Стандарте, что ссылка
NS>> будет валидной, если до этого не нарушали Стандарт.

EM> Hет, лично я спорю с утверждением о праве компилятора самовольно
EM> выбрасывать упомянутые проверки под видом "оптимизации". :) Если для
EM> какого-нибудь сферического компиятора в ваккуме, созданного
EM> исключительно для иллюстрации величия Стандарта, это еще допустимо, то
EM> для производственного - ни в коем разе.

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

. С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... И нижнее бельё на каблуках

Eugene Muzychenko

unread,
Jan 15, 2016, 4:10:15 PM1/15/16
to
Привет!

14 Jan 16 21:57, you wrote to me:

NS> если в стандарте сказано, что этого не может быть никогда, то
NS> оптимизатор должен выкинуть эту проверку.

Как здесь уже цитировалось, этого не может быть лишь в "well-defined program".
Я на это задал вопрос - кто обеспечивает соответствие программы этому
определению? Мне ответили - компилятор вместе с программистом. :) При таких
обстоятельствах, никакого основания для выкидывания компилятор не имеет. Вот
если бы он это обеспечивал полностью сам - другое дело.

Nickita A Startcev

unread,
Jan 17, 2016, 11:55:05 PM1/17/16
to
Привет, Eugene !


15 Jan 16 , 19:44 Eugene Muzychenko писал к Nickita A Startcev:


NS>> если в стандарте сказано, что этого не может быть никогда, то
NS>> оптимизатор должен выкинуть эту проверку.

EM> Как здесь уже цитировалось, этого не может быть лишь в "well-defined
EM> program". Я на это задал вопрос - кто обеспечивает соответствие
EM> программы этому определению? Мне ответили - компилятор вместе с
EM> программистом. :) При таких обстоятельствах, никакого основания для
EM> выкидывания компилятор не имеет. Вот если бы он это обеспечивал
EM> полностью сам - другое дело.

аналогия.
обработчик прерывания может изменить не-волятильную переменную, которую ждут в
цикле. означает ли это, что в циклах нельзя оптимизировать чтение переменной из
памяти и вообще заоптимизировать цикл до вечного?

bool flag;
...
flag=false;
while ( ! flag ) {};
do_some();
...

. С уважением, Hикита.
icq:240059686, lj-user:nicka_startcev
... Д/з: Реактивная куропатия

Eugene Muzychenko

unread,
Jan 18, 2016, 3:10:01 AM1/18/16
to
Привет!

18 Jan 16 06:12, you wrote to me:

NS> обработчик прерывания может изменить не-волятильную переменную,
NS> которую ждут в цикле. означает ли это, что в циклах нельзя
NS> оптимизировать чтение переменной из памяти и вообще заоптимизировать
NS> цикл до вечного?

Еще раз: компилятор может выполнять любые оптимизации при обеспечении двух
условий:

- не нарушается логика работы программы;
- не нарушаются требования, установленные стандартами/документацией.

При удалении компилятором сравнения содержимого ссылки с nullptr не выполняются
оба этих условия: первое - по очевидной причине, второе - потому, что
стандартом не установлена невозможность наличия nullptr в ссылке для _любой_
программы.

NS> bool flag;
NS> ...
NS> flag=false;
NS> while ( ! flag ) {};
NS> do_some();
NS> ...

В этом примере у компилятора _есть_ возможность убедиться в неизменности
переменной, не снабженной атрибутом volatile. В ситуации, когда с nullptr
сравнивается ссылка, "только что" инициализированная валидным объектом, она
тоже есть.
0 new messages