Explicação detalhada das referências C++ (características das referências, diferença entre referências e ponteiros, outros usos das referências)

citar

1. Introdução

Na vida, também podemos dar apelidos a alguns alunos. Tomemos "Zhang Lei" como exemplo, podemos chamá-lo de "Zhang Sanshi". Quando chamamos esse apelido, naturalmente pensaremos em "Zhang Lei", "Zhang Sanshi". é o pseudônimo de Zhang Lei, e a citação pode ser entendida desta maneira simples: no nível gramatical, uma citação é um pseudônimo .

Dois. Os operadores mais problemáticos em C++

* e & em C++ têm vários significados e têm significados diferentes sob diferentes condições de uso:
*

int *p = &a;   /1.指针
a = a * b;     /2.乘法
*p = 100;      /3.指向

&

int c = a&b;    /1.位运算 转换为二进制
int *p = &a;    /2.取地址
int  a = 100;
int & ar = a;   /3.引用

3. Definição de referência

Uma referência não é uma nova definição de uma variável, mas um alias para uma variável existente.O compilador não abrirá espaço de memória para a variável de referência e compartilhará o mesmo espaço de memória com a variável referenciada.

O formato é o seguinte :

Nome da variável de tipo e referência (nome do objeto) = entidade de referência
Observe que o espaço aqui é opcional, ou seja

  • Pode haver um espaço antes e depois do símbolo &; como segue: int & ra=a;
  • O símbolo & está ao lado do tipo, como segue: int& ra=a;
  • O símbolo & fica ao lado do nome da referência, como segue: int &ra=a;

int main()
{
int a =100; \\定义变量名
int b = a;\\将a的值赋给变量
int &c = a;\\引用 将c作为a的别名 c11中成为左值引用
return 0;
}

Aqui equivale a uma entidade tomando dois nomes como a e c, e não abre um novo espaço neste espaço.
insira a descrição da imagem aqui

4. Características das citações

  1. Deve ser inicializado ao definir uma referência
  2. sem referências nulas
  3. Não existe citação secundária
  4. Uma variável pode ter várias referências (é equivalente a uma variável com vários aliases, o que é possível)

Explicação:
int main()
{
int a = 10;
int& b = a;
int& x;
int& y = NULL;
int&& c = a;
}
insira a descrição da imagem aqui
Resumindo:
a referência em si é uma variável, mas esta variável é apenas mais uma variável e um alias, não ocupa espaço na memória, não é um ponteiro! Apenas um pseudônimo!

5. Comparando ponteiros e referências

Vamos usar a função swap como exemplo
para trocar dois valores inteiros usando ponteiros:

int my _swap (int*ap, int*bp)
{
    
    
	assert(ap != NULL && bp != NULL);
	int tmp = *ap;*ap = *bp;*bp = *ap;
}
int main()
{
    
    
	int x = 10, y = 20;
	my_swap{
    
    &x,&y);
	cout<< "x = " << x << " y = " << y << endl;
	return 0;
}

Troque dois ponteiros usando referências:

void my_swap (int& a,int& b)
{
    
    
	int tmp = a;a = b;
	b = tmp;
}
int main ()
{
    
    
	int x = 10, y = 20;my_swap(x,y) ;
	cout << " x = " << x<< " y = " << y << endl;
	return 0;
}

Quando o parâmetro formal é um ponteiro: a primeira frase deve ser afirmada, e deve-se julgar se está vazia; e ao usar ponteiros, precisamos prestar atenção: se éponteiro selvagem,Ponteiro nulo,ponteiro de invalidação.
Quando usamos referências, não há referência NULL, não há necessidade de julgar null e é mais seguro que ponteiros

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
所以:能不使用指针就尽量不要使用指针!
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Seis. A diferença entre referências e ponteiros ( ênfase )

1. Diferenças no nível gramatical

  1. Em termos de regras gramaticais, uma variável de ponteiro armazena o endereço de uma instância (variável ou objeto);
    uma referência é um alias de uma instância.
  2. O programa aloca regiões de memória para variáveis ​​de ponteiro; ele não aloca regiões de memória para referências.
int main()
{
    
    
	int a = 10;
	int* ip = &a;
	int& b = a;  \\b是a的别名 并没有分配新的空间
}
  1. Desreferenciar é adicionar "*" antes de usar o ponteiro; a referência pode ser usada diretamente.
int main()
{
    
    
	int a = 10;
	int* ip = &a;
	int& b = a;  
	*ip = 100//对于指针使用加“*”
	b = 200//引用不需要“*”
	
}
  1. O valor da variável ponteiro pode ser alterado para armazenar os endereços de diferentes instâncias;
    a referência é inicializada quando é definida e não pode ser alterada posteriormente (não pode ser uma referência a outras instâncias).
int main()
{
    
    
	int a = 10,b = 20;
	int* ip = &a;
	ip = &b ;
	int& c = a;
	c = b;   //b的值给c实则是把b的值给a,将a的值改为20
}
  1. O valor de uma variável de ponteiro pode estar vazio (NULL, nullptr); não há referências nulas.
  2. Quando uma variável de ponteiro é usada como um parâmetro formal, sua validade precisa ser testada (julgamento NULL); as
    referências não precisam ser julgadas NULL.
  3. Usar "sizeof" em uma variável de ponteiro obtém o tamanho da variável de ponteiro;
    usar "sizeof" em uma variável de referência obtém o tamanho da variável.
int main()
{
    
    
	double dx = 10;
	double* dp = &dx;
	double& a = dx; 
	printf("sizeof(dp):%d\n", sizeof(dp));
	printf("sizeof(a):%d", sizeof(a));
}

resultado da operação:
insira a descrição da imagem aqui

  1. Em teoria, não há limite para o número de níveis de ponteiros, mas há apenas um nível de referências.
    ou seja, não há referências a referências, mas pode haver ponteiros para ponteiros.

  2. ++referências têm efeitos diferentes de ++ponteiros.

Por exemplo, em termos de operações ++:

int main()
(
	int ar[5] = {
    
     1,2,34,5 };
	int* ip = ar; //数组首元素地址
	int& b = ar[O]; //数组首元素的别名叫b
	++ip;  //由0下标的地址指向1下标的地址
	++b;  //由0下标指向1下标
}

insira a descrição da imagem aqui

  1. As operações em referências reagem diretamente à entidade referenciada (variável ou objeto).
    A operação na variável ponteiro fará com que a variável ponteiro aponte para o endereço da próxima entidade (variável ou objeto); em vez de alterar o conteúdo da entidade apontada (variável ou objeto).
int main()
(
	int ar[5] = {
    
     1,2,34,5 };
	int* ip = ar; //数组首元素地址
	int& b = ar[O]; //数组首元素的别名叫b
	++(*ip); //值由1>>2 
	(*ip)++; //所有表达式结束后 进行++ 
	//有括号 先取ip的值与*结合 然后++为所指之物的++
	int x = *ip++;
	//没有括号 先将ip的值取出 与*结合 把所指之物取出(此时已与*结合完) 然后将ip取出进行++ ++后的值回写给ip 将值存储到x中
	//通过()提高了优先级
}
  1. Variáveis ​​locais ou objetos em funções não podem ser retornados por referência ou ponteiro.

    O endereço pode ser retornado quando o tempo de vida da variável não é afetado pela função

2. Diferenças no nível de montagem

No nível do assembly, uma referência é um ponteiro, mas uma referência não é um ponteiro comum, é um slot de sintaxe para ponteiros e também pode ser considerado um ponteiro comum.

int main()
{
    
    
	int a = 10;
	int* ip = &a;
	int& x = a;
	*ip = 100;
	x = 200;
}

insira a descrição da imagem aqui

7. Outros usos de referências

  1. Frequentemente citado:

Uma referência constante é, na verdade, uma referência universal que pode se referir a variáveis ​​comuns, constantes ou constantes literais .

(1) Refere-se a variáveis ​​comuns

int main()
{
    
    
	int a = 10;
	int & b = a;
    const int& c = a;
    b += 10;
    a += 10;
    c += 10;
    return 0;
}

Para este problema de erro: porque c não é modificável
insira a descrição da imagem aqui
(2) constante de referência

int main()
{
    
    
    int a = 10;
    const int b =20;
    int& x = a;
    int& y = b;  //error 不安全
    const int& y = b; //ok
    const int& z =10; //ok
    return 0;
}

insira a descrição da imagem aqui
(3) Aspas constantes literais

Ao referenciar uma constante literal, ela é dividida em duas etapas. Primeiro, defina um temporário para referir-se ao temporário em vez de referenciar a constante literal real 10.

int main()
{
    
    
    int a = 10;
    const int& z =10; //ok
    //int tmp =10;
    //const int &z = tmp;
    return 0;
}
  1. referência de matriz

Ao referenciar uma matriz, o tamanho da matriz deve ser conhecido

int main()
{
    
    
    int a = 10;
    int b = 10;
    int ar[5] = {
    
     1,2,3,4,5 };
    int& x = ar[0];  //ok
    int(&x)[5] = ar; //ok   没有[5]无法编译通过
  
    return 0;
}
  1. referência do ponteiro

Como a referência é uma variável, também posso atribuir um alias à variável do ponteiro

int main()
{
    
    
	int a = 100;
	int *p = &a;
	int * &rp = p;
 
	cout << a << endl;
	cout << *p << endl;
	cout << *rp << endl; //这里为什么要将*放在前面,因为p的类型是 int * 作为一个整体哦!!
 
	cout << p << endl;
	cout << rp << endl;
 
	getchar();
	return 0;
}
/*
100
100
100
012FF84C
012FF84C
*/

Descobrimos que a variável de ponteiro p aqui é exatamente a mesma que sua referência (alias) rp. Mas como o propósito de uma referência é semelhante ao de um ponteiro, geralmente não há necessidade de criar um alias para o ponteiro.

Acho que você gosta

Origin blog.csdn.net/weixin_56935264/article/details/124669712
Recomendado
Clasificación