2 полезно для кастинга к производному типу.
предположим Животное:
b = a as Badger;
c = a as Cow;
if (b != null)
b.EatSnails();
else if (c != null)
c.EatGrass();
станет питаемым минимумом бросков.
Поскольку он демонстрирует неопределенное поведение - вы разыменовываете нулевой указатель.
Когда вы говорите:
auto_ptr<MyClass> ptr;
, вы создаете автопоинтер, который ни на что не указывает. Это эквивалентно высказыванию:
MyClass * ptr = NULL;
Затем, когда вы говорите:
cout<<ptr->solution()<<endl;
, вы разыменовываете этот нулевой указатель. Это не определено в C ++ - для вашей реализации это работает.
std :: auto_ptr не будет автоматически создавать объект для вас. То есть ptr
в основном в существующем виде инициализируется значением null. Разыменование этого - неопределенное поведение, и вам просто повезло, и в результате вы получите 42.
Если вы действительно создадите объект:
int main(int argc, char *argv[])
{
auto_ptr<MyClass> ptr(new MyClass);
cout << ptr->solution() << endl;
return 0;
}
Вы получите ожидаемый результат.
Потому что вы не знаете вопрос к ответу xD
Кажется, вы не вызываете конструктор, верно?
Во-первых, имейте в виду, что оператор ->
в auto_ptr
по существу пересылается на содержащийся указатель. Итак, для этого обсуждения ваш код в main
становится эквивалентным:
MyClass* ptr = NULL;
cout << ptr->solution() << endl;
Затем обратите внимание, что компиляторы, как правило, реализуют функции-члены так, как если бы они не были функциями-членами с этот указатель
передан как другой аргумент функции. Итак, с точки зрения вашего текущего компилятора, ваш код в main
действует так, как если бы он был:
MyClass* ptr = NULL;
cout << solution(ptr) << endl;
с решением, записанным как:
int solution(MyClass* this) { return 42; }
. В этом случае становится очевидным, почему не было сбоя.
Однако, как уже упоминалось другими, это внутренние детали того, как компиляторы реализуют C ++, которые не определены стандартом языка. Таким образом, теоретически этот код может работать, как описано здесь, на одном компиляторе, но давать сбой или делать что-то еще совсем на другом компиляторе.
Но на практике, даже если стандарт не гарантирует такое поведение, любой конкретный компилятор может гарантируют это, если захотят. Например: поскольку MFC полагается на это поведение, очень маловероятно, что Visual Studio когда-либо перестанет его поддерживать. Конечно, вам придется исследовать каждый конкретный компилятор, в котором можно использовать ваш код, чтобы убедиться, что они действительно гарантируют такое поведение.
поскольку MFC полагается на это поведение, очень маловероятно, что Visual Studio когда-либо перестанет его поддерживать. Конечно, вам придется изучить каждый конкретный компилятор, в котором может использоваться ваш код, чтобы убедиться, что они действительно гарантируют такое поведение. поскольку MFC полагается на это поведение, очень маловероятно, что Visual Studio когда-либо перестанет его поддерживать. Конечно, вам придется исследовать каждый конкретный компилятор, в котором можно использовать ваш код, чтобы убедиться, что они действительно гарантируют такое поведение. Вы повторно не создаете экземпляр объекта.
Вы создаете только интеллектуальный указатель.
Когда вы вызываете метод, вы отменяете ссылку на указатель NULL, поэтому, как упомянул Нил, вы теперь находитесь в неопределенном поведении. Но поскольку ваш код не пытается получить доступ к каким-либо переменным-членам, он, к счастью, не дает сбоев.
Попробуйте следующее:
auto_ptr<MyClass> ptr(new MyClass);
Потому что ptr
не инициализирован, а вы ' повезло. Для этого сначала следует вызвать новый
:
auto_ptr<MyClass> ptr( new MyClass );
Вы не получаете сбоя, потому что метод «решения» не должен фактически использовать члены класса. Если бы вы возвращали участника или что-то в этом роде, вы, вероятно, получили бы сбой.