Ответ 1
В C все, что не 0, верно. Итак, вы, безусловно, можете использовать:
if (ptrToObject)
ptrToObject->doSomething();
для безопасного разыменования указателей.
C++ 11 немного меняет игру, nullptr_t
- это тип, экземпляр которого nullptr
; представление nullptr_t
зависит от конкретной реализации. Таким образом, компилятор может определить nullptr_t
так, как он хочет. Нужно только убедиться, что он может обеспечить надлежащее ограничение на приведение nullptr_t
к различным типам - для которых допускается логическое значение - и убедиться, что он может различать nullptr_t
и 0.
Таким образом, nullptr
будет правильно и неявно приведен к логическому false
, если компилятор следует спецификации языка C++ 11. И приведенный выше фрагмент все еще работает.
Если вы удалите ссылочный объект, ничего не изменится.
delete ptrToObject;
assert(ptrToObject);
ptrToObject = nullptr;
assert(!ptrToObject);
Из-за того, как долго я пишу такие if-ы, это вторая задача - проверить правильность указателей перед использованием, введя if (object *) и затем вызывая его члены.
Нет. Пожалуйста, поддерживайте правильный график объектов (желательно используя уникальные/умные указатели). Как указано, нет способа определить, указывает ли указатель, который не является nullptr
, на действительный объект или нет. В любом случае на вас лежит ответственность за поддержание жизненного цикла... вот почему оболочки указателей существуют в первую очередь.
Фактически, поскольку жизненный цикл общих и слабых указателей четко определен, они имеют синтаксический сахар, который позволяет вам использовать их так, как вы хотите использовать голые указатели, где допустимые указатели имеют значение, а все остальные nullptr
:
Общий
#include <iostream>
#include <memory>
void report(std::shared_ptr<int> ptr)
{
if (ptr) {
std::cout << "*ptr=" << *ptr << "\n";
} else {
std::cout << "ptr is not a valid pointer.\n";
}
}
int main()
{
std::shared_ptr<int> ptr;
report(ptr);
ptr = std::make_shared<int>(7);
report(ptr);
}
Слабое
#include <iostream>
#include <memory>
void observe(std::weak_ptr<int> weak)
{
if (auto observe = weak.lock()) {
std::cout << "\tobserve() able to lock weak_ptr<>, value=" << *observe << "\n";
} else {
std::cout << "\tobserve() unable to lock weak_ptr<>\n";
}
}
int main()
{
std::weak_ptr<int> weak;
std::cout << "weak_ptr<> not yet initialized\n";
observe(weak);
{
auto shared = std::make_shared<int>(42);
weak = shared;
std::cout << "weak_ptr<> initialized with shared_ptr.\n";
observe(weak);
}
std::cout << "shared_ptr<> has been destructed due to scope exit.\n";
observe(weak);
}
Теперь, C++ будет делать то же самое для указателей? Если передать символ *, например, в оператор if?
Итак, чтобы ответить на вопрос: с голыми указателями, нет. С завернутыми указателями, да.
Оберните ваши указатели, ребята.