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 ++x
sã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::string
e produz um rvalue que designa este objeto, 1729
nã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 &)1
está 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 const
não é mais necessário, embora o objeto z
vinculado 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 5
diretamente. 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 r
na função pode ser substituído por *ptr
e r
nã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 x
obras apenas dentro do bloco que contém a declaração de x
referência.
const
:)
const