Formulário errado:
int &z = 12;
Forma correta:
int y;
int &r = y;
Pergunta :
Por que o primeiro código está errado? Qual é o " significado " do erro no título?
Formulário errado:
int &z = 12;
Forma correta:
int y;
int &r = y;
Pergunta :
Por que o primeiro código está errado? Qual é o " significado " do erro no título?
(ostringstream() << "x=" << x).str()
Respostas:
C ++ 03 3.10 / 1 diz: "Cada expressão é um lvalue ou um rvalue." É importante lembrar que valor versus valor valor é uma propriedade de expressões, não de objetos.
Lvalues nomeia objetos que persistem além de uma única expressão. Por exemplo, obj, *ptr, ptr[index], e ++xsão todos lvalues.
Os valores R são temporários que evaporam no final da expressão completa em que vivem ("no ponto e vírgula"). Por exemplo, 1729, x + y, std::string("meow"), e x++são todos rvalues.
O operador address-of requer que seu "operando deve ser um lvalue". se pudéssemos pegar o endereço de uma expressão, a expressão seria um lvalue, caso contrário, seria um rvalue.
&obj; // valid
&12; //invalid
int & = 12;é inválido, o padrão diz que um literal de string é um lvalue, outros literais são rvalues.
std::string("meow")constrói um objeto do tipo std::stringe produz um rvalue que designa este objeto, 1729não tem efeito colateral e produz valor 1729 como um rvalue do tipo int.
"Lvalues name objects that persist beyond a single expression."é 100% correta. Pelo contrário, seu exemplo (const int &)1está incorreto, porque NÃO é um objeto "nomeado".
int &z = 12;
No lado direito, um objeto temporário do tipo inté criado a partir do literal integral 12, mas o temporário não pode ser vinculado a uma referência não const. Daí o erro. É o mesmo que:
int &z = int(12); //still same error
Por que um temporário é criado? Porque uma referência deve se referir a um objeto na memória, e para um objeto existir, ele deve ser criado primeiro. Como o objeto não tem nome, ele é um objeto temporário . Não tem nome. A partir dessa explicação, ficou bastante claro por que o segundo caso está bom.
Um objeto temporário pode ser vinculado à referência const, o que significa que você pode fazer o seguinte:
const int &z = 12; //ok
Para fins de integridade, gostaria de acrescentar que o C ++ 11 introduziu rvalue-reference, que pode vincular a um objeto temporário. Portanto, em C ++ 11, você pode escrever isto:
int && z = 12; //C+11 only
Observe que existe em vez &&de &. Observe também que constnão é mais necessário, embora o objeto zvinculado seja um objeto temporário criado a partir de integral literal 12.
Como o C ++ 11 introduziu rvalue-reference , int&agora é chamado de lvalue-reference .
12é uma constante de tempo de compilação que não pode ser alterada ao contrário dos dados referenciados por int&. O que você pode fazer é
const int& z = 12;
void f( vector<int> const & )idiomática para passar um vetor que não deve ser modificado. O problema agora é que isso f( vector<int>(5) )seria incorreto e o usuário teria que fornecer uma sobrecarga diferente, o void f( vector<int> v ) { f(v); }que é trivial.
f( vector<int>(5) ), o compilador cria um temporário e então vincula a referência àquele temporário, e da mesma forma se houve uma conversão implícita de 5diretamente. Isso permite que o compilador gere uma única assinatura para a função e permite uma única implementação da função pelo usuário. A partir daí, um comportamento semelhante é definido para o restante dos usos de referências constantes para consistência.
T const & r = *ptr;qualquer uso posterior de rna função pode ser substituído por *ptre rnão precisa existir em tempo de execução) ou pode ter que ser implementado mantendo o endereço do objeto que ele atribui (considere armazenar uma referência como um membro de um objeto) - que é implementado como um ponteiro autodereferenciado.
Estas são as regras da linguagem C ++:
12) é um "rvalue"int &ri = 12;está malformadoVocê tem que entender que essas são regras C ++. Eles simplesmente são.
É fácil inventar uma linguagem diferente, digamos C ++ ', com regras ligeiramente diferentes. Em C ++ ', seria permitido criar uma referência não const com um rvalue. Não há nada inconsistente ou impossível aqui.
Mas isso permitiria algum código arriscado onde o programador poderia não obter o que pretendia, e os designers de C ++ decidiram corretamente evitar esse risco.
As referências são "ponteiros ocultos" (não nulos) para coisas que podem mudar (lvalores). Você não pode defini-los como uma constante. Deve ser uma coisa "variável".
EDITAR::
Estou pensando em
int &x = y;
quase equivalente a
int* __px = &y;
#define x (*__px)
onde __pxé um nome novo, e as #define xobras apenas dentro do bloco que contém a declaração de xreferência.
const:)
const