Pergunta

Quer dizer que não usá-lo quando necessário para as funções, classes, se, ao mesmo tempo, switch, try-catch.

Eu não sabia que isso poderia ser feito como isso até que eu vi este SO pergunta .

No link acima, Eli mencionou que "Eles usá-lo para dobrar seu código em seções lógicas que não se enquadram em uma função, classe, loop, etc. que normalmente ser dobrado."

Que outros usos estão lá, além dos mencionados?

É uma boa idéia usar chaves para limitar o escopo de suas variáveis ??e expandir o alcance somente se necessário (trabalhando em uma base de "necessidade de acesso")? Ou é realmente bobo?

Que tal usar escopos apenas para que você pode usar os mesmos nomes de variáveis ??em diferentes âmbitos, mas no mesmo escopo maior? Ou é uma melhor prática de reutilizar a mesma variável (se você quiser usar o mesmo nome de variável) e salve em desalocá e alocar (acho que alguns compiladores podem otimizar sobre isso?)? Ou é melhor usar diferentes nomes de variáveis ??completamente?

Foi útil?

Solução

eu faço se eu estou usando um recurso que eu quero libertar em um momento específico, por exemplo:

void myfunction()
{
  {
  // Open serial port
     SerialPort port("COM1", 9600);
     port.doTransfer(data);
  } // Serial port gets closed here.

  for(int i = 0; i < data.size(); i++)
     doProcessData(data[i]);
  etc...
}

Outras dicas

Eu não usaria chaves para o efeito por dois motivos.

  1. Se a sua função particular é suficientemente grande que você precisa fazer vários truques de escopo, talvez quebrar a função em pequenos sub-funções.

  2. Apresentando chaves para definir o escopo de reutilizar nomes de variáveis ??só vai levar a confusão e problemas no código.

Apenas meus 2 centavos, mas eu vi um monte de esses tipos de coisas em outras melhores materiais de prática.

O comum uso mais "não-padrão" de escopo que eu uso regularmente é utilizar um mutex escopo.

void MyClass::Somefun()
{
    //do some stuff
    {
        // example imlementation that has a mutex passed into a lock object:
        scopedMutex lockObject(m_mutex); 

        // protected code here

    } // mutex is unlocked here
    // more code here
}

Isto tem muitas vantagens, mas o mais importante é que o bloqueio será sempre limpo, mesmo se uma exceção é lançada no código protegido.

C ++ :

Às vezes você precisa de introduzir um nível cinta extra de espaço para reutilizar nomes de variáveis ??quando faz sentido fazê-lo:

switch (x) {
    case 0:
        int i = 0;
        foo(i);
        break;
    case 1:
        int i = 1;
        bar(i);
        break;
}

O código acima não compilar. Você precisa fazer isso:

switch (x) {
    case 0:
        {
            int i = 0;
            foo(i);
        }
        break;
    case 1:
        {
            int i = 1;
            bar(i);
        }
        break;
}

O uso mais comum, como já foi dito, é garantir que os destruidores executado quando você quer que eles. Também é útil para tornar o código específico de plataforma um pouco mais claro:

#if defined( UNIX )
    if( some unix-specific condition )
#endif
    {
        // This code should always run on Windows but 
        // only if the above condition holds on unix
    }

Código construído para Windows não vê o caso, apenas as chaves. Isto é muito mais clara do que:

#if defined( UNIX )
    if( some unix-specific condition ) {
#endif
        // This code should always run on Windows but 
        // only if the above condition holds on unix
#if defined( UNIX )
    }
#endif

Pode ser uma benção para os geradores de código. Suponha que você tenha um SQL compilador embutido (ESQL); ele pode querer converter uma instrução SQL em um bloco de código que precisa de variáveis ??locais. Usando um bloco, ele pode reutilizar fixo nomes de variáveis ??mais e mais, em vez de ter que criar todas as variáveis ??com nomes separados. Concedido, isso não é muito difícil, mas é mais difícil do que o necessário.

Como já foi dito, este é bastante comum em C ++ devido à (inicialização aquisição de recursos é) todo-poderoso RAII idiom / padrão.

Para programadores Java (e talvez C #, eu não sei) este será um conceito estranho porque os objetos à base de pilha e GC mata RAII. IMHO, ser capaz de colocar objetos na pilha é a maior vantagem única de C ++ sobre Java e faz bem escrito C ++ código mais limpo MUITO do que o código Java bem escrito.

Eu só usá-lo quando eu preciso lançar algo por meio de RAII e mesmo assim só quando deveria ser lançado tão cedo quanto eu possivelmente pode (liberando um bloqueio, por exemplo).

Programação em Java Eu tenho muitas vezes queria âmbito limite dentro de um método, mas isso nunca ocorreu-me a usar uma etiqueta. Desde que eu maiúsculas meus rótulos quando usá-los como alvo de uma pausa, usando um caso misto rotulado bloco como você têm sugerido é exatamente o que eu queria nestas ocasiões.

Muitas vezes, os blocos de código são muito curtos para sair em um método pequeno, e muitas vezes o código em um método do quadro (como startup (), ou shutdown ()) e é realmente melhor para manter o código juntos em um método.

Pessoalmente eu odeio a planície flutuante / balançando chaves (apesar de que é porque somos um rigoroso bandeira do estilo loja travessão), e eu odeio o marcador de comentário:

// yuk!
some code
{
scoped code
}
more code

// also yuk!
some code
/* do xyz */ {
    scoped code
    }
some more code

// this I like
some code
DoXyz: {
    scoped code
    }
some more code

Consideramos o uso de "if (true) {" porque o Java especificação diz especificamente estes serão otimizadas na compilação (assim como todo o conteúdo de um if (false) - é um recurso de depuração), mas eu odiava que em os poucos lugares que tentou fazê-lo.

Então eu acho que a sua ideia é boa, nada bobo. Eu sempre pensei que eu era o único que queria fazer isso.

Sim, eu uso essa técnica por causa de RAII. Eu também uso desta técnica na planície C , uma vez que traz as variáveis ??mais próximos. Claro, eu deveria estar pensando em romper as funções ainda mais.

Uma coisa que eu fazer isso é provavelmente estilisticamente é controversa colocar a chave de abertura na linha da declaração ou colocar um comentário direito sobre ele. Eu quero diminuir a quantidade de espaço vertical desperdiçado. Isto é baseado na recomendação Guia de Estilo ++ C Google. .

/// c++ code
/// references to boost::test
BOOST_TEST_CASE( curly_brace )
{
  // init
  MyClass instance_to_test( "initial", TestCase::STUFF ); {
    instance_to_test.permutate(42u);
    instance_to_test.rotate_left_face();
    instance_to_test.top_gun();
  }
  { // test check
    const uint8_t kEXP_FAP_BOOST = 240u;
    BOOST_CHECK_EQUAL( instance_to_test.get_fap_boost(), kEXP_FAP_BOOST);
  }
}

Eu concordo com agartzke. Se você sentir que você precisa para segmentar blocos de códigos lógicos maiores para facilitar a leitura, você deve considerar refatoração para limpar membros ocupados e desordenado.

Ele tem o seu lugar, mas eu não acho que fazê-lo de modo que $ foo pode ser uma variável aqui e uma variável diferente não , dentro da mesma função ou outro (lógico, ao invés de lexical) escopo é uma boa idéia. Mesmo que o compilador pode entender isso perfeitamente, parece muito provável que tornar a vida difícil para os seres humanos que tentam ler o código.

A empresa que eu estou trabalhando em tem uma política de análise estática para manter declarações de variáveis ??locais perto do início de uma função. Muitas vezes, o uso é muitas linhas após a primeira linha de uma função, então não posso ver a declaração e a primeira referência ao mesmo tempo na tela. O que fazer para 'contornar' a política é a de manter a declaração perto da referência, mas oferecem a possibilidade adicional usando chaves. Ele aumenta o recuo, porém, e alguns podem argumentar que torna o mais feio código.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top