当我;“重新初始化”;指针 我目前正在编写C++代码,我遇到了一些我不理解的行为。假设我有一个自定义类(我不确定它是否与类中发生的事情有关),我想创建一个指向该类的指针: AliAODEvent* aod;
现在,在我做了这个指针之后,我想把它分配到一个内存位置。在我使用的框架中,我想要指向的对象已经存在于某个地方,所以我所做的是当我;“重新初始化”;指针 我目前正在编写C++代码,我遇到了一些我不理解的行为。假设我有一个自定义类(我不确定它是否与类中发生的事情有关),我想创建一个指向该类的指针: AliAODEvent* aod;,c++,pointers,initialization,C++,Pointers,Initialization,现在,在我做了这个指针之后,我想把它分配到一个内存位置。在我使用的框架中,我想要指向的对象已经存在于某个地方,所以我所做的是 AliAODEvent* aod = (This is where the object I want to point to goes); 我现在意识到我应该只使用aod=(指向的对象),语句 AliAODEvent* aod = (This is where the object I want to point to goes); aod = (This is w
AliAODEvent* aod = (This is where the object I want to point to goes);
我现在意识到我应该只使用aod=(指向的对象)但是我很好奇,当我试图从本质上“重新初始化”指针时发生了什么。有什么想法?在C++中, < P>,语句
AliAODEvent* aod = (This is where the object I want to point to goes);
aod = (This is where the object I want to point to goes);
表示“请为我创建一个名为aod
的AliAODEvent*
类型的新变量,并为其分配一个特定变量。”另一方面,语句
AliAODEvent* aod = (This is where the object I want to point to goes);
aod = (This is where the object I want to point to goes);
意味着“找到一个名为<代码> AOD的现有变量,并将其赋值给一个新的位置。”这里的区别在于,通过包含类型的名称,C++认为您给出的是一个引入新变量的声明,而不是一个赋值语句,它使用一个现有变量并改变它指向的位置。这就是语言的设计方式
第二种方法有效而第一种方法无效的原因是,您最终试图获取存在的东西并对其进行更改,这意味着您不应该提供声明。一般来说,如果要声明变量,则只应在语句中包含该变量的类型,否则只应使用其名称。在这种情况下,您不是在重新初始化指针,而是尝试创建同名指针,这将是一个错误,除非它位于不同的作用域块中
即:
在这种情况下,aod变量将是正常的(尽管可能会显示警告),这将是一个不同的vaiable,一旦它的作用域(“}”)结束,它将不再存在。以下代码:
A* aod = &x;
A* aod = &y;
声明了两个变量,且格式不正确。大多数编译器都应该拒绝它,但如果设置正确,某些编译器可能会允许它通过
这里发生的事情是编译器为第一个变量创建了存储,并将x
的地址存储到其中。然后,它为第二个变量创建了额外的存储,并隐藏了原始变量
此时,程序将x
和y
的值存储在不同的内存位置,但您只能引用第二个aod
,直到它超出范围
这通常称为“阴影”,仅在作用域之间合法:
#include <iostream>
struct A {};
A a, b, c;
A* ptr = &a;
void report(A* p) {
std::cout << (void*) &a << ", " << (void*) &b << ", " << (void*) &c
<< ": " << (void*) p << "\n";
}
int f() {
std::cout << "f() ";
report(ptr);
}
int main() {
report(ptr);
if (ptr != nullptr) {
A* ptr = &b;
report(ptr);
if (ptr != nullptr) {
A* ptr = &c;
f();
report(ptr);
}
report(ptr);
}
report(ptr);
}
这会分配两个A
s,但不会释放第一个,因为我们从不告诉它,我们只是覆盖该值。编译器不会跟踪何时不再引用动态对象
int main() {
A* aod = nullptr;
if (aod == nullptr) { // start new scope
A x;
aod = &x;
} // end scope, `x` is destroyed.
use(aod);
}
此代码引入了一个错误:<代码> AOD 指向“代码> x/CODE >的地址,但是 X<代码>在 } /Cube >超出范围时被破坏,因此该指针为“代码>悬空”,引用无效内存。
< P> C++中有声明和初始化。
声明变量意味着要求操作系统在内存中为其分配一个位置。初始化变量意味着第一次在该内存地址设置值。您可以同时执行这两项操作:
int x = 10; // Declares x, then initialises it to 10
<>在C++中,不允许多次声明变量:
int x; // Declares x
int x; // Tries to declare another variable also called x, fails (ERROR)
但是,只要两个变量在不同的作用域中,就可以使用相同的名称声明它们:
#include <iostream>
int x = 10;
int main()
{
int x = 20;
{
int x = 30;
std::cout << x << ", " << ::x << std::endl; // Prints '30, 10'
}
std::cout << x << ", " << ::x << std::endl; // Prints '20, 10'
return 0;
}
#包括
int x=10;
int main()
{
int x=20;
{
int x=30;
std::cout在给指针一个指向现有位置的地址时,您不想再次使用它左边的类型说明符,因为该变量已经存在(即声明变量)。当您在第一个aod
范围内时,您将无法再次声明新变量aod
此外,为了清楚起见,只有在赋值运算符之后有对象的地址时,才是正确的,而不是对象本身。您可以在另一个对象的名称之前使用&
运算符将对象的地址赋给指针,以获取其地址:
Object* objectPointer = &existingObject; //point objectPointer to the address of existingObject
或者,通过一种方法
Object* objectPointer = method()
其中method()
的返回类型为Object*
(指向对象的指针)
还可以使用new
操作符在堆上创建新对象:
Object* objectPointer = new Object("args");
完成后,必须使用delete
操作符将其删除
delete objectPointer;
请记住,仅仅因为指针超出范围并停止存在,并不意味着它所指向的内存会发生这种情况。除了已经说过的内容外,还应该出现一些编译错误,如错误:“aod”的重新定义。
请务必注意,引用与指针不同,不能被重新定义除此之外,重新分配指针没有什么特别之处,因为它只是一个包含内存地址的整数变量(假设采用简化方法)。“我想将其分配到内存位置”-请确保您理解术语“分配到”在这里,您是在给指针赋值,而不是相反。这是最基本的,请注意在编程中如何表达。
delete objectPointer;