int *puntero = 0; // El puntero no apunta a nada.
{
int valor = 0;
puntero = &valor; // Apunta al objeto 'valor'.
}
// Aqui, 'puntero' sigue apuntando a 'valor' aunque dicho objeto ya no exista!
puntero = new int; // 'puntero' puede gestionar memoria dinamica!
指针是 C 和 C++ 中管理动态内存的唯一机制;运算符new在被调用时生成指针,从数组到指针的转换是常见的做法,反之亦然。
Address of :如果我们在一个指针上使用get-address操作符,我们会在指针上加一层指针,即:一个指针的地址有指向指针的类型,和前一个地址的类型将是指向指针的指针(等等到无穷大):
int valor = 0;
int *puntero_int = &valor; // Puntero a int.
int **puntero_a_puntero = &puntero_int; // Puntero a puntero a int
int ***puntero_a_puntero_a_puntero = &puntero_a_puntero; // Puntero a puntero a puntero a int
取消引用:如果我们在指针上使用取消引用运算符,我们将访问指向的对象,允许我们修改所述对象:
int valor = 0;
int *puntero_int = &valor; // Puntero a int.
*puntero_int = *puntero_int + 1;
char *puntero_char = 0;
int *puntero_int = 0;
// Esta condicion se cumple siempre.
if (sizeof(puntero_char) == sizeof(puntero_int)) std::cout << "Eureka!";
预选赛。
const可以用四种不同的方式或volatile以四种不同的方式来限定指针:
没有限定符:这是我们迄今为止一直在研究的限定符:
int *puntero = 0; // Sin cualificadores
此模式允许您定位缺少限定符的对象:
int valor = 0;
int *puntero = &valor;
限定目标对象:限定应用于目标对象:
const int *puntero = 0; // Apuntamos a int constantes.
此模式允许您定位具有相同或更低资格的对象:
int valor = 0;
const int valor_constante = 0;
// ERROR! 'valor_constante' solo puede ser apuntado por punteros con la misma cualificacion!
int *puntero = &valor_constante;
// Correcto! Usamos un puntero a entero constante
const int *puntero_a_constante = &valor_constante;
// Correcto! Apuntamos a un objeto con cualificacion inferior
const int *otro_puntero_a_constante = &valor;
int valor1 = 0;
int valor2 = 0;
int *const puntero_constante = &valor1;
*puntero_constante = *puntero_constante + 1; // valor1 sera 1
puntero_constante = &valor2; // ERROR! 'puntero_constante' no puede ser cambiado
int valor1 = 0;
int valor2 = 0;
const int *const puntero_constante_a_constante = &valor1;
// ERROR! el objeto apuntado es constante!
*puntero_constante_a_constante = *puntero_constante_a_constante + 1;
// ERROR! 'puntero_constante_a_constante' no puede ser cambiado
puntero_constante_a_constante = &valor2;
int valor1 = 1;
int valor2 = 2;
int &referencia; // ERROR! 'referencia' necesita referenciar un objeto.
int &otra_referencia = valor1; // Correcto! Referenciamos 'valor1'.
修改目标对象。
引用不能改变他们引用的对象,对引用的任何赋值操作都会修改被引用的对象而不是引用:
int valor1 = 1;
int valor2 = 2;
int &referencia = valor1;
referencia = valor2;
int valor1 = 1;
int &referencia = valor1;
referencia = referencia + 1;
上面的示例将导致它valor1的值2noreferencia指向int内存中的下一个。
Address of:无法获取引用的内存地址,相反,获得的内存地址将是被引用对象的内存地址:
int valor = 0;
int &referencia = valor;
// Esta condicion se cumple siempre.
if (&valor == &referencia) std::cout << "Eureka!";
取消引用:在引用上使用取消引用运算符将导致编译错误,除非被引用的对象接受该运算符:
int valor = 0;
struct S { int operator *() { return 0; } } s;
int &referencia_a_int = valor;
S &referencia_a_S = s;
std::cout << *referencia_a_int; // ERROR! int no acepta operador unario *
std::cout << *referencia_a_S; // Correcto! S acepta operador unario *
Size:如果我们sizeof在引用上使用运算符,我们将获得被引用对象的大小:
char c = 0;
int i = 0;
char &referencia_char = c;
int &referencia_int = i;
// Esta condicion solo se cumple si char e int son del mismo tamanyo.
if (sizeof(referencia_char) == sizeof(referencia_int)) std::cout << "Oh oh...";
int valor = 0;
const int valor_constante = 0;
int &referencia1 = valor;
int &referencia2 = valor_constante; // ERROR! Se necesita una referencia constante
有条件的引用:他们可以引用有条件和没有条件的对象:
int valor = 0;
const int valor_constante = 0;
// Correcto, referencia constante a objeto no constante
const int &referencia1 = valor;
// Correcto! referencia constante a objeto constante
const int &referencia2 = valor_constante;
它们是不同的类型。第一个 (
int *
) 是指向整数的指针。第二个 (int &
) 是整数引用。指针。
指针指向对象,它们的值是一个内存地址。出于实际目的,它们将是一种只能指向其他对象的数据类型;作为类比,它们可以是邮政编码(指向市区)或车辆登记(指向车辆)或护照号码(指向人)。
生命周期。
指向类型的指针在其生命周期中
tipo *
可以指向多个类型的对象,tipo
甚至可以根本不指向任何对象或指向不存在的对象:指针是 C 和 C++ 中管理动态内存的唯一机制;运算符
new
在被调用时生成指针,从数组到指针的转换是常见的做法,反之亦然。修改目标对象。
使用指针,您几乎可以指向内存的任何部分,这就是为什么指针被认为既危险又有用的原因;指针的这种灵活性可以允许检查或修改不属于正在运行的程序的内存(用于分析或黑客攻击),这可能导致程序崩溃。
操作。
算术:算术运算可以用指针执行:通过向指针添加一个值,我们获得一个指向从原始指针移位的内存区域的指针,其字节数与指向值的大小一样多:
通过将 1 添加到
puntero_char
,我们将使指针指向的内存区域比它最初指向的区域晚 1 个字节(在char
占用一个字节的系统上),减去 1puntero_int
将使指针指向的内存区域早 4 个字节它最初指向的区域(在int
占用 4 个字节或 32 位的系统上)。在这两种情况下,我们都将指向我们不应该读取或写入的内存,因为两个指针都已初始化,0
并且操作系统通常禁止访问内存地址0
(以及接近的各种值0
)。Address of :如果我们在一个指针上使用get-address操作符,我们会在指针上加一层指针,即:一个指针的地址有指向指针的类型,和前一个地址的类型将是指向指针的指针(等等到无穷大):
取消引用:如果我们在指针上使用取消引用运算符,我们将访问指向的对象,允许我们修改所述对象:
上面的例子使它
valor
包含 value1
。Size:如果我们
sizeof
在指针上使用运算符,无论指向的类型如何,我们都会得到相同的大小,这个大小会根据系统架构而有所不同;通常指针的大小与处理器字的大小相匹配:预选赛。
const
可以用四种不同的方式或volatile
以四种不同的方式来限定指针:没有限定符:这是我们迄今为止一直在研究的限定符:
此模式允许您定位缺少限定符的对象:
限定目标对象:限定应用于目标对象:
此模式允许您定位具有相同或更低资格的对象:
也就是说,我们可以使用指针指向没有限定的对象,就好像它们被限定了
const
or一样volatile
。限定指针:限定应用于指针:
请注意,限定符在星号 (
*
) 之后,在这种情况下,我们正在创建一个指向非常量整数的常量指针。由于指针是常量,我们不能让它指向另一个对象,但我们可以修改指向的对象:两者都合格:资格适用于两者:
请注意,限定符位于星号 ( ) 的两侧
*
,在这种情况下,我们正在创建一个指向常量对象的常量指针。所以我们将无法修改它指向的对象或指向的对象的值:和前面的例子一样,我们看到指针可以指向限制较少的对象。
参考。
引用,引用对象,不包含指向被引用对象的地址,它们是被引用对象。出于所有实际目的,引用与它引用的对象没有区别。作为一个类比,它们将是一个与另一个量子键合的粒子。
生命周期。
对类型的引用
tipo &
仅指tipo
向其生命周期中的类型对象,这就是为什么必须在其声明时对其进行分配的原因:修改目标对象。
引用不能改变他们引用的对象,对引用的任何赋值操作都会修改被引用的对象而不是引用:
该语句
referencia = valor2;
没有使其referencia
引用,valor2
而是将 的值分配给valor2
引用的对象referencia
,即:它将valor1
获取值2
。操作。
算术:由于引用在其整个生命周期中只指向一个对象,因此不可能通过算术运算来修改被引用的对象;相反,对引用执行的操作将应用于被引用对象,而不是引用本身,就像对被引用对象执行操作一样:
上面的示例将导致它
valor1
的值2
noreferencia
指向int
内存中的下一个。Address of:无法获取引用的内存地址,相反,获得的内存地址将是被引用对象的内存地址:
取消引用:在引用上使用取消引用运算符将导致编译错误,除非被引用的对象接受该运算符:
Size:如果我们
sizeof
在引用上使用运算符,我们将获得被引用对象的大小:预选赛。
因为在实践中引用是它所引用的同一个对象,所以只能引用具有相同或更低资格的对象。与指针不同,不可能仅限定对被引用对象的引用,因此:
无条件引用:它们可以无条件引用对象:
有条件的引用:他们可以引用有条件和没有条件的对象:
int*
代表一个指针。int&
代表参考。他们怎么长得像?
在内部,我们可以认为这两个元素都被视为指针。也就是说,在进行修改时,您正在更改第三个变量的值:
它们之间有什么区别?
变化有几个:
该参考没有给你指出的内存地址:
您不能更改引用指向的对象:
它不能
delete
在引用上执行:在参考文献中,不必使用间接运算符:
你怎么知道什么时候使用每种类型?
当您不需要访问使它们与指针不同的任何功能时,应该使用引用,因为它们的使用比指针的情况更简单、更清晰。
例如,如果一个函数返回一个引用,我们可以假设一旦使用完返回的变量,我们就不必担心清除内存。