Оценка на късо съединение в C++

Може би пропускам нещо доста просто, но получавам срив, когато дереферирам указател, въпреки че проверявам точката в самото начало на израза.

if( var1 &&
    bool1 || bool2 &&
    var1->DoSomething() )
{

}

var1 е нулев указател, но Var1->Dosomething() все още се извиква. Моето разбиране е, че && и || оператор в C++ са късо съединение, така че ако var1 беше нула, тогава той просто щеше да прекрати в самото начало. Или има нещо друго, което пропускам?


person user1149438    schedule 14.01.2012    source източник
comment
Когато се съмнявате, поставете скоби!   -  person Cody Gray    schedule 14.01.2012


Отговори (3)


Приоритетът на оператор е ключът тук. Тъй като && има по-висок приоритет от ||, вашият израз е еквивалентен на

(var1 && bool1) || (bool2 && var1->DoSomething() )

Така че, тъй като var1 се оценява като false, bool1 не се оценява и (var1 && bool1) дава false, следователно (bool2 && var1->DoSomething()) трябва да бъде оценено. И ако bool2 се окаже вярно, тогава var1->DoSomething() също ще бъде оценено, което ще доведе до недефинирано поведение.

Просто добавете няколко скоби (за конкретното изразно дърво, което ви е необходимо) и ще се оправите.

person Armen Tsirunyan    schedule 14.01.2012

Тъй като && има по-висок приоритет от ||, вашият израз се анализира като (var1 && bool1) || (bool2 && var1->DoSomething()). Тъй като var1 е нулев указател, оценката на късо съединение означава, че bool1 не се оценява, а лявата страна на || се оценява като невярна. По този начин, за да се открие стойността на израза, дясната страна трябва да бъде оценена (т.е. оценката на късо съединение не се включва тук!). Дясната страна на || е bool2 && var1->DoSomething(), следователно, ако bool2 е вярно, var1->DoSomething() ще бъде оценено. Обърнете внимание също, че дори за var1 не-null, резултатът от e-израза не винаги ще бъде това, което вероятно сте очаквали.

person celtschk    schedule 14.01.2012

просто. && има по-висок приоритет, така че вашият израз гласи:

if( ( var1 && bool1 ) || ( bool2 && var1->DoSomething()) )

опитвам

if( var1 && ( bool1 || bool2 ) && var1->DoSomething() )

в противен случай първият израз car1 && bool1 е неуспешен и вторият израз се оценява. тъй като bool2 връща true, очевидно вашият указател е дерефериран, ако bool2 е true.

вижте тук за списък с приоритети: http://en.cppreference.com/w/cpp/language/operator_precedence или използвайте google.

person ted    schedule 14.01.2012