2015-02-22 1 views
1

Итак, после 20 лет от C++, я вернулся в него. Я за свою жизнь не могу обойти эту проблему. Я работаю с [на работе] классами, я передал ссылки адреса, а не ссылки на указатели. Этот маленький пример foo() ниже, почему я не могу вернуть NULL или nullptr? Какое правило я нарушаю, что забываю?C++ retro newbie: адрес ссылки

int& foo(int &i) 
{ 
    if (i > 10) 
    { 
    // or return nullptr; 
    return NULL; 
    } 
    return i; 
} 
+1

Вы нарушаете правило, что ссылки не могут быть NULL. –

+0

Вы не можете вернуть 'nullptr', потому что он имеет тип указателя, но' int & 'объявляет тип возвращаемого типа ссылочным. – emlai

+1

C++ не имеет понятия «адрес». «Ссылки на указатели», по крайней мере, так, как вы это понимаете. Я предлагаю вам прочитать разницу между указателями и ссылками. – Sneftel

ответ

1

Почему я не могу вернуть NULL или nullptr?

Поскольку вы объявили функцию, возвращающую ссылку на междунар. Ссылки должны всегда «указывать» на фактический int, который существует. A nullptr поэтому не является допустимым значением. (Нулевой указатель не конвертируется в ссылку в целое, это конвертируемая только в указатель для инт.)

Решение 1:

Объявить функцию, чтобы вернуть указатель на междунар:

int* foo(int &i) 
{ 
    if (i > 10) 
    { 
    return nullptr; // or NULL, or 0. (Since NULL is a macro expanding to `0` or `nullptr` anyway.) 
    } 
    return &i; // Return the address of i, aka a pointer to i. 
} 

Решение 2:

Объявить значение int, которое семантически идентично возврату нулевого значения.

int& foo(int &i) 
{ 
    static int nullValue = 0; 
    if (i > 10) 
    { 
    // or return nullptr; 
    return nullValue; 
    } 
    return i; 
} 

Теперь каждый раз, когда i > 10 верно, то функция возвращает ссылку на статической локальной переменной, равной 0 (вы можете изменить фактическое значение, если это необходимо).

Конечно, если return i возвращает значение идентично nullValue, то функция абонент не может знать, вернулась ли функция ссылки на nullValue или какое-то фактическое значение i.

+0

Спасибо за это. После прочтения первого и второго ответов я понимаю, что я делал неправильно. Это очень помогло. –

0

В C++ NULL определяется реализация, но обычно это просто целое число:

#define NULL 0 

или

#define NULL nullptr // с C++ 11

В обоих случаях ошибка является несоответствие типов:

error: invalid initialization of non-const reference of type 'int&' 
     from an rvalue of type 'int' 
     #define NULL 0 
        ^
+0

Спасибо за это. После прочтения первого и второго ответов я понимаю, что я делаю неправильно. Это очень помогло мне. –

+0

Хуже того, если 'NULL' определяется как' 0', тогда 'return NULL' вернет ссылку на локальную переменную *, которая будет уничтожена при выходе из функции. – emlai

+0

@zenith not true, если #define NULL 0, он не компилируется, и ошибка была выбрана так, как я вставлял. Это так, чтобы предотвратить ошибку, о которой вы говорили. – 4pie0

1

Нет такой вещи, как «адресные ссылки». Есть «ссылки», и они отличаются от указателей. Ссылки на C++ - очень мощная языковая функция, отсутствующая на многих других языках (например, C или Java).

Ссылка лучше всего изображается как другое имя для существующего объекта. Или еще лучше, как сам объект. Ссылка на объект.

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

Они делают это по соображениям безопасности.

Нет, они этого не делают. Если бы они сказали это, тогда это не имеет смысла. Вы не используете ссылки для производительности (по крайней мере, не для неконстантных ссылок), вы используете их для правильности.

int& foo(int &i) 
{ 
    if (i > 10) 
    { 
    // or return nullptr; 
    return NULL; 
    } 
    return i; 
} 

Там нет такого понятия, как "нулевой ссылки". Помните, что ссылка является объектом. Итак, что ваша функция foo здесь возвращает, фактически является самим объектом. Не указатель на него, не его адрес, а сам объект.

А какой объект NULL или nullptr be? Это не имеет смысла. Не может быть объекта, который ничего.

Если вам нужно иметь специальное «ничего» в вашей бизнес-логике, вы можете использовать что-то вроде boost::optional. Или, может быть, вам действительно нужен указатель. Это зависит.

, а не ссылки на указатели.

Ссылки указателя существуют, но они не связаны с вашим примером.

Вот ссылка на указатель:

int main() 
{ 
    int x = 0; 
    int* ptr = &x; 
    int*& y = ptr; // "y" is now a different name for "ptr" 
} 
+0

Вы явно очень умный человек. Спасибо, что поделились с вами своим ответом. –

1

Вы могли бы find this ответ проницательный.

Короткий ответ: В C++ ссылки никогда не может быть NULL (или любой версии NULL как nullptr), потому что он всегда должен быть безопасным для снятия ссылки.

+0

Это имеет смысл. Спасибо за аналогию. –

0

Нулевые ссылки не допускаются - «Ссылка должна быть инициализирована для ссылки на действительный объект или функцию. [Примечание: в частности, нулевая ссылка не может существовать в четко определенной программе, поскольку единственный способ создать такую ссылка должна была бы привязать его к «объекту», полученному разыменованием нулевого указателя, что вызывает неопределенное поведение. Как описано в 9.6, ссылка не может быть привязана непосредственно к битовому полю.] ». Источник: http://en.wikipedia.org/wiki/Reference_%28C%2B%2B%29

Смежные вопросы