Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.05.2012, 01:44   #1
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию Ссылка как опциональный параметр

Попалась на глаза, условно такая конструкция:
Код:
int somefunc (int x, bool & y = *(bool*) 0)
{
	int ret = 0;
	// какие-то вычисления c ret
	// ....
	if (&y) // проверить задан ли опциональный параметр
		y = (ret > 0);

	return ret;
}

///
bool f;
somefunc(1);
somefunc(2, f);
Всвязи с этим вопрос: верно ли это стилистически?
Я бы использовал указатель, т.к. для меня ссылка подразумевает явный параметр. Но может кто использует такой стиль?
EUGY вне форума Ответить с цитированием
Старый 03.05.2012, 02:01   #2
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Попалась на глаза, условно такая конструкция:
Код:
int somefunc (int x, bool & y = *(bool*) 0)
{
	int ret = 0;
	// какие-то вычисления c ret
	// ....
	if (&y) // проверить задан ли опциональный параметр
		y = (ret > 0);

	return ret;
}

///
bool f;
somefunc(1);
somefunc(2, f);
Всвязи с этим вопрос: верно ли это стилистически?
Я бы использовал указатель, т.к. для меня ссылка подразумевает явный параметр. Но может кто использует такой стиль?
Это не просто неверно стилистически, это неверно с точки зрения корректности программы. Так нельзя делать.
netrino вне форума Ответить с цитированием
Старый 03.05.2012, 02:05   #3
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Да вот я че-то не вижу некорректности в поведении программы.
Это меня и смутило.
EUGY вне форума Ответить с цитированием
Старый 03.05.2012, 02:14   #4
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Да вот я че-то не вижу некорректности в поведении программы.
Это меня и смутило.
Некорректность программы с точки зрения языка не гарантирует некорректность программы с точки зрения пользователя. Как пример, переполнение знаковых переменных ведёт к неопределённому поведению, но чаще всего мы увидим отрицательное минимальное значение в конкретных реализациях.
Код:
printf ("%d", INT_MAX + 1);  // Поведение не определено, но в большинстве случаев мы увидим -2147483648 при 32-х битном int
То, что программа не падает и работает как ожидалось - случайность.
netrino вне форума Ответить с цитированием
Старый 03.05.2012, 02:24   #5
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
То, что программа не падает и работает как ожидалось - случайность.
Но ведь передача по ссылке по своей сути - это передача адреса аргумента.
Если опционально задан нулевой адрес и этот факт проверяется в функции, то почему работоспособность - случайность?
EUGY вне форума Ответить с цитированием
Старый 03.05.2012, 02:35   #6
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Но ведь передача по ссылке по своей сути - это передача адреса аргумента.
Если опционально задан нулевой адрес и этот факт проверяется в функции, то почему работоспособность - случайность?
Хотя бы потому что это описано в стандарте
Цитата:
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. ]
Ссылка может указывать только на объект. Поскольку в C разыменование по нулевому указателю не определено, то и объекта по этому адресу быть не может, а значит ссылаться на него невозможно.

То есть нет гарантии, что программа будет работать на других платформах, нет гарантии, что она будет работать при компиляции другим компилятором, нет даже гарантий, что она будет корректно работать при компиляции тем же компилятором с другими опциями или уровнями оптимизации.

Последний раз редактировалось netrino; 03.05.2012 в 02:41.
netrino вне форума Ответить с цитированием
Старый 03.05.2012, 02:49   #7
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Вот не вижу в упор противоречий со стандартом.
В приведенном отрывке говорится о разыменовывании нулевого указателя.
Но ведь в функции этот факт проверяется и не делается попытки присвоения значения в несуществующий объект.
PS
Или само взятие адреса такой ссылки уже некорректное действие?

Последний раз редактировалось EUGY; 03.05.2012 в 02:55.
EUGY вне форума Ответить с цитированием
Старый 03.05.2012, 03:01   #8
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Вот не вижу в упор противоречий со стандартом.
В приведенном отрывке говорится о разыменовывании нулевого указателя.
Но ведь в функции этот факт проверяется и не делается попытки присвоения значения в несуществующий объект.
Нет, там говорится, что нулевая ссылка не может существовать в корректно написанной программе на C++, ввиду того, что для связи ссылки с объектом по указателю, нужно этот указатель разыменовать. Если указатель нулевой, то разыменование его не определено, следовательно, программа некорректна. И, несмотря на то, что всё работает, у Вас нет гарантии, что компилятор не вставит разыменование нулевой ссылки до проверки её на ноль, или же вообще не устранит проверку на агрессивных уровнях оптимизации (ведь зачем проверять то, что по стандарту произойти не может). С чем-то подобным когда-то столкнулись разработчики ядра линукс, об этом упоминали в статьях различных, если в двух словах, то был такой код (условно):
Код:
void contains_null_check(int *P) {
  int dead = *P;
  if (P == 0)
    return;
  *P = 4;
}
А в после оптимизаций получался такой:
Код:
void contains_null_check(int *P) {
  *P = 4;
}
Проблема была в том, что первой строкой шло разыменование указателя. "Раз мы его разыменовали, значит он точно не ноль, а потому проверку можно убрать, как лишний код" - подумал компилятор и удалил всё лишнее =)
Пример я взял с блога LLVM, там же можно найти серию статей на тему неопределённого поведения в C++ и чем это чревато, рекомендую прочесть.
http://blog.llvm.org/2011/05/what-ev...ould-know.html
http://blog.llvm.org/2011/05/what-ev...d-know_14.html
http://blog.llvm.org/2011/05/what-ev...d-know_21.html
netrino вне форума Ответить с цитированием
Старый 03.05.2012, 03:09   #9
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Да, спасибо.
Интуитивно чувствовал, что плохой стиль.
Убедили!



PS.
___
Собственно вопрос возник не на пустом месте. Исправляю чужой проект.
Подобные нулевые ссылки по умолчанию там раскиданы по многим функциям. Любопытно, как внести минимум поправок.
Будет компилироватся на студийном VS2010.

Может так:
Код:
// Microsoft Specific
__declspec (thread) bool DEFBOOL = false; // прости-господи

int somefunc (int x, bool & y = DEFBOOL)
{
	int ret = 0;
	// какие-то вычисления c ret
	// ....
	if (&y)
		y = (ret > 0);

	return ret;
}

Последний раз редактировалось EUGY; 03.05.2012 в 04:44. Причина: PS
EUGY вне форума Ответить с цитированием
Старый 03.05.2012, 05:28   #10
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Да, спасибо.
Интуитивно чувствовал, что плохой стиль.
Убедили!



PS.
___
Собственно вопрос возник не на пустом месте. Исправляю чужой проект.
Подобные нулевые ссылки по умолчанию там раскиданы по многим функциям. Любопытно, как внести минимум поправок.
Будет компилироватся на студийном VS2010.

Может так:
Код:
// Microsoft Specific
__declspec (thread) bool DEFBOOL = false; // прости-господи

int somefunc (int x, bool & y = DEFBOOL)
{
	int ret = 0;
	// какие-то вычисления c ret
	// ....
	if (&y)
		y = (ret > 0);

	return ret;
}
__
PPS. Нет, торможу, не спасет.
Значит все переписывать, и передавать указатель!
EUGY вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Матрица как входящий параметр inmyacid Общие вопросы Delphi 6 19.04.2012 15:39
Матрица как параметр miftayka Visual C++ 2 09.04.2012 20:19
Параметр-ссылка со значением по умолчанию wandererindreams Общие вопросы C/C++ 14 12.08.2011 13:00
как сделать параметр ГОСЕАН БД в Delphi 6 20.04.2009 07:24
Как передать параметр? Иллидан Общие вопросы Delphi 8 12.07.2008 12:57