当我;“重新初始化”;指针 我目前正在编写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=(指向的对象) < 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;