Вопреки популярному мнению возможно иметь ссылку, которая является ПУСТОЙ.
int * p = NULL;
int & r = *p;
r = 1; // crash! (if you're lucky)
Предоставленный, это намного тяжелее относится к ссылке - но если Вы будете управлять им, Вы порвете волосы, пытаясь найти его. Ссылки не по сути безопасны в C++!
Технически это недопустимая ссылка , не нулевая ссылка. C++ не поддерживает нулевые ссылки как понятие, поскольку Вы могли бы найти на других языках. Существуют другие виды недопустимых ссылок также. Любой недопустимая ссылка повышает призрак [1 119] неопределенное поведение , как использование недопустимого указателя было бы.
фактическая ошибка находится в разыменовании Нулевого указателя до присвоения на ссылку. Но я не знаю ни о каких компиляторах, которые генерируют любые ошибки на том условии - ошибка распространяет к точке далее вперед в коде. Это - то, что делает эту проблему таким образом коварной. Большую часть времени при разыменовании Нулевого указателя Вы отказываете прямо в том пятне, и не требуется большой отладки для понимания его.
Мой пример выше короток и изобретен. Вот более реальный пример.
class MyClass
{
...
virtual void DoSomething(int,int,int,int,int);
};
void Foo(const MyClass & bar)
{
...
bar.DoSomething(i1,i2,i3,i4,i5); // crash occurs here due to memory access violation - obvious why?
}
MyClass * GetInstance()
{
if (somecondition)
return NULL;
...
}
MyClass * p = GetInstance();
Foo(*p);
я хочу повторить, что единственный способ получить нулевую ссылку через уродливый код, и как только у Вас есть он, Вы получаете неопределенное поведение. никогда не имеет смысл проверять на нулевую ссылку; например, можно попробовать if(&bar==NULL)...
, но компилятор мог бы оптимизировать оператор из существования! Действительная ссылка никогда не может быть ПУСТОЙ так от представления компилятора, сравнение всегда является ложью, и это свободно устранить if
пункт как мертвый код - это - сущность неопределенного поведения.
надлежащий способ остаться вне проблемы состоит в том, чтобы не разыменовывать Нулевого указателя для создания ссылки. Вот автоматизированный способ выполнить это.
template
T& deref(T* p)
{
if (p == NULL)
throw std::invalid_argument(std::string("NULL reference"));
return *p;
}
MyClass * p = GetInstance();
Foo(deref(p));
Для более старого взгляда на эту проблему от кого-то с лучшими навыками письма, см. Нулевые ссылки от Jim Hyslop и Herb Sutter.
Для другого примера опасностей разыменовать нулевого указателя см. Представлять неопределенное поведение при попытке портировать код на другую платформу Raymond Chen.
Эта статья довольно хорошо объясняет проблему.
Короче говоря, очень большие или очень маленькие числа с плавающей запятой могут привести к потере точности во время вычислений.
Добавление 1 и 1 как числа с плавающей запятой или удвоения не должно приводить ни к чему, кроме 2.
Мне трудно поверить, что 0,5 + 1,5 дает что-либо, кроме 2.
Все эти числа могут быть правильно представлены в двоичной системе с плавающей запятой.
Мне неприятно говорить, что я не верю вашим примерам, но я не верю. : -)
Однако я верю, что у вас могут возникнуть проблемы с числом, например 1.1.
Почему? Поскольку 1/10 оказывается повторяющимся десятичным числом в двоичном формате.
Проблема возникает при попытке преобразовать числа с плавающей запятой между десятичным и двоичным представлениями. Некоторые числа подходят для поездки, но другие являются приблизительными.
Однако, если ваши примеры действительно работают таким образом, я понятия не имею, что происходит, и хотел бы знать.
Не уверен, ищете ли вы объяснение или решение, но поскольку вы уже получили указатели на хорошие объяснения ....
Если вам нужно, чтобы ваши числа вели себя как целые числа, используйте целые числа . Если вам нужна конечная степень точности (например, два десятичных знака для полей, представляющих деньги), все равно сохраните ее как целое число, но умножьте его на любой коэффициент 10, который вам нужен, чтобы избавиться от десятичной дроби, когда вы помещаете его в базу данных, и делите на то же самое, когда вы вытаскиваете его обратно.
Итак, если вы представляете виджет стоимостью 3,99 доллара вы указываете 399 в поле WIDGET.cost.
Не знаю, применимо ли это к вашей ситуации или нет. Но общее практическое правило состоит в том, что числа с плавающей запятой ВСЕГДА являются всего лишь приближением. :-) Если точность имеет значение, найдите способ использовать целые числа.
Не ожидайте целых чисел при работе с типами с плавающей запятой.
числа с плавающей запятой ВСЕГДА являются приблизительными. :-) Если точность имеет значение, найдите способ использовать целые числа.
По моему опыту,