Pergunta

Estou revisando o código de um colega, e vejo que ele possui diversas constantes definidas no escopo global como:

const string& SomeConstant = "This is some constant text";

Pessoalmente, isso me cheira mal porque a referência se refere ao que presumo ser um objeto "anônimo" construído a partir de um determinado array de caracteres.

Sintaticamente, é legal (pelo menos no VC++ 7) e parece funcionar, mas na verdade prefiro que ele remova o & para que não haja ambigüidade quanto ao que está fazendo.

Então, isso é VERDADEIRAMENTE seguro e legal e estou obcecado?O objeto temporário que está sendo construído tem vida útil garantida?Sempre presumi que objetos anônimos usados ​​dessa maneira eram destruídos após o uso...


Portanto, minha pergunta também poderia ser generalizada para a vida útil do objeto anônimo.O padrão determina o tempo de vida de um objeto anônimo?Teria o mesmo tempo de vida de qualquer outro objeto no mesmo escopo?Ou é dado apenas o tempo de vida da expressão?


Além disso, ao fazer isso como local, obviamente o escopo é diferente:

class A
{
    string _str;

public:
    A(const string& str) :
        _str(str)
    {
        cout << "Constructing A(" << _str << ")" << endl;
    }

    ~A()
    {
        cout << "Destructing A(" << _str << ")" << endl;
    }
};

void TestFun()
{
    A("Outer");
    cout << "Hi" << endl;
}

Mostra:

Construindo A (Externo);Destruindo A (Externo);Oi

Foi útil?

Solução

É completamente legal.Não será destruído até que o programa termine.

EDITAR: Sim, é garantido:

"Todos os objetos que não têm duração dinâmica de armazenamento, não têm duração de armazenamento de roscas e não são locais têm duração de armazenamento estático.O armazenamento desses objetos deve durar a duração do programa (3.6.2, 3.6.3). "

-- Rascunho de trabalho de 2008, padrão para linguagem de programação C++, § 3.7.1 pág.63

Como observou Martin, esta não é a resposta completa.O projeto padrão de notas adicionais (§ 12.2, p.250-1):

"Os temporários do tipo de classe são criados em vários contextos:Vinculando um rvalue a uma referência (8.5.3) [...] Mesmo quando a criação do objeto temporário é evitada (12,8), todas as restrições semânticas devem ser respeitadas como se o objeto temporário tivesse sido criado....] Objetos temporários são destruídos como o último passo para avaliar a expressão total (1.9) que (lexicamente) contém o ponto em que foram criados....] Existem dois contextos em que os temporários são destruídos em um ponto diferente do que o final da expressão total....] O segundo contexto é quando uma referência está vinculada a um temporário.O temporário ao qual a referência é ligada ou o temporário que é o objeto completo de um subobjetivo ao qual a referência é ligada persiste durante a vida útil da referência, exceto conforme especificado abaixo. "

Testei em g++ se isso faz você se sentir melhor.;)

Outras dicas

Sim, é válido e legal.

const string& SomeConstant = "This is some constant text";

// Is equivalent too:

const string& SomeConstant = std::string("This is some constant text");

Assim você está criando um objeto temporário.
Este objeto temporário está vinculado a um const& e, portanto, tem seu tempo de vida estendido até o tempo de vida da variável ao qual está vinculado (ou seja, mais longo que a expressão na qual foi criado).

Isto é garantido pela norma.

Observação:

Embora seja legal.Eu não usaria isso.A solução mais fácil seria convertê-lo em const std::string.

Uso:

Nesta situação, como a variável está no escopo global, ela é válida para toda a extensão do programa.Portanto, ele pode ser usado assim que a execução entrar em main() e não deve ser acessado após a execução sair de main().

Embora tecnicamente possa estar disponível antes disso, seu uso em construtores/destruidores de objetos globais deve ser moderado com o problema conhecido da ordem de inicialização de variáveis ​​globais.

Pensamentos extras:

Este, por outro lado, não sofrerá com o problema:

char const* SomeConstant = "This is some constant text";

E pode ser usado em qualquer momento.Apenas um pensamento.

Pode ser legal, mas ainda assim feio.Deixe de fora a referência!

const string SomeConstant = "This is some constant text";

É tão legal quanto feio.

É legal estender uma variável temporária com um const referência, esta é usada por Alexandrescu EscopoGaurd veja esta excelente explicação de Herb Sutter chamada Um candidato para o "Mais importante const".

Dito isto, este caso específico é um abuso deste recurso do C++ e a referência deve ser removida deixando um claro const string.

Declará-lo como const (o que significa que não pode ser alterado) e depois torná-lo uma referência, o que implica que alguém pode alterá-lo, parece, no mínimo, uma má forma.Além disso, como tenho certeza que você entende, variáveis ​​globais são RUINS e raramente necessárias.

Ok, pessoal, corrijam-me se eu estiver errado, mas aqui estão minhas conclusões ouvindo todas as suas excelentes respostas:

A) é sintaticamente e logicamente legal, o & estende a vida útil do temporário/anônimo além do nível de expressão até a vida da referência.Eu verifiquei isso no VC++7 com:

class A { 
    public: A() { cout << "constructing A" << endl; }
    public: ~A() { cout << "destructing A" << endl; }
};

void Foo()
{
    A();
    cout << "Foo" << endl;
}

void Bar()
{
    const A& someA = A();
    cout << "Bar" << endl;
}

int main()
{
    Foo();    // outputs constructing A, destructing A, Foo
    Bar();    // outputs constructing A, Bar, destructing A
    return 0;
}

B) Embora seja legal, pode levar a alguma confusão quanto ao tempo de vida real e a referência nestes casos não lhe dá nenhum benefício de declará-la como não-referência, portanto, a referência provavelmente deve ser evitada e pode até ser um espaço extra .Como não há nenhum benefício nisso, é uma ofuscação desnecessária.

Obrigado por todas as respostas, foi uma discussão muito interessante.Então, resumindo:Sim, é sintaticamente legal, não, não é tecnicamente perigoso, pois a vida útil é estendida, mas não acrescenta nada e pode adicionar custos e confusão, então por que se preocupar?

Parece certo?

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