Pro / con: инициализация переменной в условном выражении - PullRequest
16 голосов
/ 26 сентября 2008

В C ++ вы можете инициализировать переменную в операторе if, например так:

if (CThing* pThing = GetThing())
{
}

Почему можно считать это плохим или хорошим стилем? Каковы преимущества и недостатки?

Лично мне нравится этот стиль, потому что он ограничивает область действия переменной pThing, поэтому его нельзя использовать случайно, когда он равен NULL. Однако мне не нравится, что вы не можете сделать это:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}

Если есть способ заставить вышеуказанное работать, пожалуйста, напишите. Но если это просто невозможно, я все равно хотел бы знать, почему.

Вопрос заимствован здесь, похожая тема, но PHP.

Ответы [ 11 ]

19 голосов
/ 26 сентября 2008

Важно то, что объявление в C ++ не является выражением.

bool a = (CThing* pThing = GetThing()); // not legit!!

Вы не можете делать как объявление, так и логическую логику в операторе if, спецификация языка C ++ специально разрешает либо выражение, либо объявление.

if(A *a = new A)
{
    // this is legit and a is scoped here
}

Как мы можем узнать, определен ли a между одним термином и другим в выражении?

if((A *a = new A) && a->test())
{
    // was a really declared before a->test?
}

Укуси пулю и воспользуйся внутренним if. Правила области видимости полезны, а ваша логика ясна:

if (CThing* pThing = GetThing())
{
    if(pThing->IsReallySomeThing())
    {
    }
}
4 голосов
/ 26 сентября 2008

О преимуществах:

Всегда рекомендуется определять переменные, когда они вам нужны, а не в строке. Это сделано для улучшения читабельности вашего кода, поскольку можно определить, что такое CThing, без прокрутки и поиска там, где он был определен.

Сокращение области видимости до цикла loop / if приводит к тому, что переменная не ссылается после выполнения блока кода, что делает ее кандидатом на сборку мусора (если язык поддерживает эту функцию).

3 голосов
/ 20 января 2010
if (CThing* pThing = GetThing())

Это плохой стиль , потому что внутри if вы не предоставляете логическое выражение. Вы предоставляете CThing*.

CThing* pThing = GetThing();
if (pThing != NULL)

Это хороший стиль.

2 голосов
/ 26 сентября 2008

К вашему сведению, некоторые старые компиляторы Microsoft C ++ (я думаю, Visual Studio 6 и .NET 2003) в некоторых случаях не совсем соблюдают правило области видимости.

for(int i = 0; i > 20; i++) {
     // some code
}

cout << i << endl;

Я должен выйти из области видимости, но это был действительный код. Я считаю, что это было сыграно как особенность, но, на мой взгляд, это просто несоблюдение. Несоблюдение стандартов - это плохо. Так же, как веб-разработчик о IE и Firefox.

Может ли кто-нибудь с VS проверить и проверить, все ли еще действует?

2 голосов
/ 26 сентября 2008

Одна из причин, по которой я обычно этого не делаю, заключается в общей ошибке пропущенного '=' в условном тесте. Я использую lint с ошибкой / предупреждениями, установленными, чтобы поймать их. Затем он будет кричать обо всех назначениях внутри условных выражений.

2 голосов
/ 26 сентября 2008

Этот должен не работает в C ++ , начиная с , даже если он поддерживает оценку короткого замыкания . Возможно Не пытайтесь сделать следующее:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}

ошибка .. см. ответ Уэсли Тарла

0 голосов
/ 07 мая 2018

Так много всего. Прежде всего, голые указатели. Пожалуйста, избегайте их всеми средствами. Используйте ссылки, необязательно, unique_ptr, shared_ptr. В качестве последнего средства напишите свой собственный класс, который занимается владением указателем и ничем иным.

Используйте унифицированную инициализацию, если вам может потребоваться C ++ 11 (C ++ 14 предпочтительнее, чтобы избежать дефектов C ++ 11): - он избегает путаницы = vs == и более строг при проверке аргументов, если они есть. 1003 *

if (CThing thing {})
{
}

Убедитесь, что реализовано operator bool, чтобы получить предсказуемое преобразование из CThing в bool. Однако имейте в виду, что другие люди, читающие код, не увидят operator bool сразу. Явные вызовы методов обычно более читабельны и обнадеживают. Если вам может потребоваться C ++ 17, используйте синтаксис инициализатора.

if (CThing thing {}; thing.is_good())
{
}

Если C ++ 17 не является опцией, используйте объявление выше, если другие предложили.

{
  CThing thing {};
  if (thing.is_good())
  {
  }
}
0 голосов
/ 26 сентября 2008

Это приемлемая и хорошая практика кодирования. Тем не менее, люди, которые не имеют низкого уровня кодирования, вероятно, не согласятся.

0 голосов
/ 26 сентября 2008

также обратите внимание, что если вы пишете код на C ++, вы хотите, чтобы компилятор предупреждал о «=» в условном выражении (которое не является частью объявления), об ошибке.

0 голосов
/ 26 сентября 2008

Я считаю это опасным. Приведенный ниже код намного безопаснее, и закрывающие скобки будут по-прежнему ограничивать область действия pThing так, как вы хотите.

Я предполагаю, что GetThing () иногда возвращает NULL, поэтому я добавил это забавное предложение в оператор if (). Он предотвращает вызов IsReallySomething () для указателя NULL.

{
    CThing *pThing = GetThing();
    if(pThing ? pThing->IsReallySomeThing() : false)
    {
    // Do whatever
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...