Привет!
Почему в качестве значения ссылки можно передать NULL, но никак нельзя проверить, что NULL передан, и как предотвратить возможность передачи NULL?
Пример компилируется GCC 3.4.5, при выполнении, естественно, runtime error.
#include <iostream>
using namespace std;
class foo {
public:
void bar(const string &str) {
// if (str != NULL) <-- как проверить ссылку на NULL???
cout << str << endl;
}
};
int main() {
foo f;
f.bar(NULL);
return 0;
};
Здравствуйте, Аноним, Вы писали:
А>Привет!
А>Почему в качестве значения ссылки можно передать NULL, но никак нельзя проверить, что NULL передан, и как предотвратить возможность передачи NULL?
А>Пример компилируется GCC 3.4.5, при выполнении, естественно, runtime error.
Попробуй пошагово продебажить программу и погляди где именно падает.
A>Всё смешалось в доме Облонских.
хватит глумиться
ту Аноним:
компилятор НУЛЛ пытаются к std::string неявно преобразовать и падает в конструкторе std::string(const char*), когда туда 0 приходит
Здравствуйте, Аноним, Вы писали:
А>ту Аноним:
А>компилятор НУЛЛ пытаются к std::string неявно преобразовать и падает в конструкторе std::string(const char*), когда туда 0 приходит
Спасибо, а то я без отладчика работаю
Здравствуйте, <Аноним>, Вы писали:
А>Почему в качестве значения ссылки можно передать NULL, но никак нельзя проверить, что NULL передан, и как предотвратить возможность передачи NULL?
Ты немножко не врубился.
Во-первых.
f.bar(NULL) <==> f.bar(string(NULL)) — смотрим на сигнатуры конструкторов std::string...
Точно! Есть конструктор string::string(const char* str), принимающий на вход сишную строку. Ненулевую! Вот поэтому-то оно и падает.
А до передачи ссылки на сконструированный объект дело не доходит.
Кстати, string::operator!= тоже имеет сигнатуру (const char*), тоже принимающую ненулевую строку. Так что в этом месте оно тоже рухнет.
Во-вторых.
Срочно забудь про ссылки из шарпа, бейсика и т.п.
В С++ указатель и ссылка — это совершенно не одно и то же, хотя
зачастую ссылка реализуется через указатель.
Тут я даже побоюсь делать развёрнутый комментарий, поскольку объём его потянет на главу учебника, как минимум. Так что берёшь хорошую книжку по С++ и вперёд.
Основное отличие: ссылки не бывают нулевыми. Получить нулевую ссылку можно только посредством неопределённого поведения (разыменовав нулевой указатель, либо нахимичив со смещением базы, либо грамотно расстреляв память).
Если же ты хочешь передавать отсылку к объекту-либо-его-отсутствию, то так и передавай указатель. Если хочешь передавать копию объекта или его отсутствие, и не боишься мегакрутого программирования — то смотри boost::optional.
А в данном конкретном случае тебе нужна не нулевая ссылка, а пустая строка. То есть, "".
Так и пиши
void foo::bar(const string& str)
{
if(str != "") // или !str.empty(), или str != string()
cout << str << endl;
}
int main()
{
foo f;
f.bar(""); // или f.bar(string());
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Здравствуйте, Аноним, Вы писали:
А>Почему в качестве значения ссылки можно передать NULL, но никак нельзя проверить, что NULL передан, и как предотвратить возможность передачи NULL?
Вот так (иногда) можно:
#include <iostream>
#include <string>
using namespace std;
class foo {
public:
void bar(const string &str) {
if (&str != NULL)
cout << str << endl;
}
};
int main() {
foo f;
f.bar(*static_cast<const string*>(NULL));
return 0;
};
Но не нужно.
Стандарт не разрешает иметь в программе "нулевую ссылку", то есть никакой гарантии, что такое будет работать в будущем, хотя возможно на конкретной платформе с конкретным компилятором оно работает сейчас. В этом случае используй константный указатель, даже если никакие другие возможности указателя тебе не нужны:
#include <iostream>
#include <string>
using namespace std;
class foo {
public:
void bar(const string * const pstr) {
if (pstr != NULL)
cout << *pstr << endl;
}
};
int main() {
foo f;
f.bar(NULL);
return 0;
};
Здравствуйте, Аноним, Вы писали:
А>Спасибо, а то я без отладчика работаю
настолько суров?
Здравствуйте, Аноним, Вы писали:
A>>Всё смешалось в доме Облонских.
А>хватит глумиться
А>ту Аноним:
А>компилятор НУЛЛ пытаются к std::string неявно преобразовать и падает в конструкторе std::string(const char*), когда туда 0 приходит
Из примера не совсем понятно, что человек хочет сделать.
У меня возникла мысль, что он путает ссылки и указатели. И в примере хочет использовать
void bar(const string* str);
куда будет передавать некоторую строчку, либо 0, если параметр не используется.
Возможно, наоборот — пустая строка должна свидетельствовать о том, что параметр не используется.