C++ 与使用指针按引用传递数组混淆

C++ 与使用指针按引用传递数组混淆,c++,arrays,pointers,reference,C++,Arrays,Pointers,Reference,几个小时前我刚问了一个问题,我完全被答案中指出的东西弄糊涂了()。有些人对我的新问题反应有点消极,所以我翻阅了我关于指针的书,这对我帮助不大。我又来了 在上一个问题中,我有一个函数void builder(int aSize1、int aSize2、int aSize3、int***frequencies),我认为该函数会为传入的int***frequencies参数的3d数组动态分配内存并对其进行初始化。但是,有人告诉我,只有一个副本将被传递到函数中,我将只为副本而不是原始副本分配和初始化。因

几个小时前我刚问了一个问题,我完全被答案中指出的东西弄糊涂了()。有些人对我的新问题反应有点消极,所以我翻阅了我关于指针的书,这对我帮助不大。我又来了

在上一个问题中,我有一个函数
void builder(int aSize1、int aSize2、int aSize3、int***frequencies)
,我认为该函数会为传入的
int***frequencies
参数的3d数组动态分配内存并对其进行初始化。但是,有人告诉我,只有一个副本将被传递到函数中,我将只为副本而不是原始副本分配和初始化。因此,他们建议我改用引用,将函数原型呈现为
void builder(int aSize1、int aSize2、int aSize3、int***&frequencies)

然而,我记得就在昨天,当我第一次偶然发现使用指针通过引用传递的概念时,人们也可以操作指针的数据。也就是说

void change_what_this_points_to( int* a )
{
    *a = 42;
}
此函数确实会更改输入函数的指针的值

那么,我的问题是,为什么前者通过副本而后者通过真实交易?除了其中一个有更多的星号之外,我看不出这两个函数之间有什么区别

任何帮助都将不胜感激。谢谢

此函数

void change_what_this_points_to( int* a )
{
    *a = 42;
}
不会更改指针本身。它更改指针指向的整数对象

如果要更改指针本身,则应按以下方式编写函数

void change_what_this_points_to( int * &a )
{
    a = new int( 42 );
}
void change_what_this_points_to( int **a )
{
    *a = new int( 42 );
}
或者用下面的方法

void change_what_this_points_to( int * &a )
{
    a = new int( 42 );
}
void change_what_this_points_to( int **a )
{
    *a = new int( 42 );
}
因此,返回到您的函数,您应该声明它

void builder(int aSize1, int aSize2, int aSize3, int*** &frequencies);
或者

void builder(int aSize1, int aSize2, int aSize3, int**** frequencies);
此函数

void change_what_this_points_to( int* a )
{
    *a = 42;
}
不会更改指针本身。它更改指针指向的整数对象

如果要更改指针本身,则应按以下方式编写函数

void change_what_this_points_to( int * &a )
{
    a = new int( 42 );
}
void change_what_this_points_to( int **a )
{
    *a = new int( 42 );
}
或者用下面的方法

void change_what_this_points_to( int * &a )
{
    a = new int( 42 );
}
void change_what_this_points_to( int **a )
{
    *a = new int( 42 );
}
因此,返回到您的函数,您应该声明它

void builder(int aSize1, int aSize2, int aSize3, int*** &frequencies);
或者

void builder(int aSize1, int aSize2, int aSize3, int**** frequencies);

另一个答案说得很好,我只是想加上我的两分钱,以防万一。把指针想象成内存中的地址。您将该地址传递到一个函数中,该函数在其中写入一些内容。然后,在调用函数之后,您可以查看内存中的同一位置,并查看其中的值

假设您有以下代码:

void SetValue(int *a){ *a = 10;}
void DoWork()
{
    int a; 
    SetValue(&a); 
}
SetValue函数将指向int的指针作为一个参数,或者我们会认为是内存中存储int的地址。然后,该函数只需将数字10写入传入的地址

然后,方法DoWork为int创建内存,并将该内存的地址传递给函数。因此,当DoWork返回存储“a”的内存时,其值为10。听起来你已经从你的问题中得到了这个,但想从这里开始以防万一

现在让我们假设您想要一个函数来为您分配内存。你真正要求函数做的是分配内存并告诉我内存在哪里。所以你可以用一个指针返回值,也就是

int* AllocateMemoryForMe()
{
    return new int(); //Creates memory for an int, let's pretend it's at location 0x100
}
void DoWork()
{
    int* a = NULL; // a has a value of 0x00
    a = AllocateMemoryForMe(); //a will now have the value of 0x100
    *a = 10; //We now write 10 to memory location 0x100
}
或者你也可以用一个指针。如果您这样做,您实际上需要做的是将内存中的一个位置传递到函数中,以便将分配内存的地址写入该位置,从而将指针指向一个指针。因此,当函数返回时,您可以查看这个地址,看看新创建的内存的地址是什么。例如:

void AllocateMemoryForMe(int** x)
{
    *x = new int(); //allocates memory for an int, let's pretend it's at memory location 0x200
}
void DoWork()
{
    int** a = new int*(); //Creates memory for an int pointer. Let's pretend it allocates memory at location 0x100. 
    AllocateMemoryForMe(a); //pass memory location 0x100 to the function.
    //Right now the address of a is still 0x100 but the data at the memory location is 0x200. This is the address of the int we want to write to.
    **a = 10; //This will now write 10 to the memory location allocated by the AllocateMemoryForMe() function. 

}

另一个答案说得很好,我只是想加上我的两分钱,以防万一。把指针想象成内存中的地址。您将该地址传递到一个函数中,该函数在其中写入一些内容。然后,在调用函数之后,您可以查看内存中的同一位置,并查看其中的值

假设您有以下代码:

void SetValue(int *a){ *a = 10;}
void DoWork()
{
    int a; 
    SetValue(&a); 
}
SetValue函数将指向int的指针作为一个参数,或者我们会认为是内存中存储int的地址。然后,该函数只需将数字10写入传入的地址

然后,方法DoWork为int创建内存,并将该内存的地址传递给函数。因此,当DoWork返回存储“a”的内存时,其值为10。听起来你已经从你的问题中得到了这个,但想从这里开始以防万一

现在让我们假设您想要一个函数来为您分配内存。你真正要求函数做的是分配内存并告诉我内存在哪里。所以你可以用一个指针返回值,也就是

int* AllocateMemoryForMe()
{
    return new int(); //Creates memory for an int, let's pretend it's at location 0x100
}
void DoWork()
{
    int* a = NULL; // a has a value of 0x00
    a = AllocateMemoryForMe(); //a will now have the value of 0x100
    *a = 10; //We now write 10 to memory location 0x100
}
或者你也可以用一个指针。如果您这样做,您实际上需要做的是将内存中的一个位置传递到函数中,以便将分配内存的地址写入该位置,从而将指针指向一个指针。因此,当函数返回时,您可以查看这个地址,看看新创建的内存的地址是什么。例如:

void AllocateMemoryForMe(int** x)
{
    *x = new int(); //allocates memory for an int, let's pretend it's at memory location 0x200
}
void DoWork()
{
    int** a = new int*(); //Creates memory for an int pointer. Let's pretend it allocates memory at location 0x100. 
    AllocateMemoryForMe(a); //pass memory location 0x100 to the function.
    //Right now the address of a is still 0x100 but the data at the memory location is 0x200. This is the address of the int we want to write to.
    **a = 10; //This will now write 10 to the memory location allocated by the AllocateMemoryForMe() function. 

}

它们意味着你传递一个指针的副本,而不是它指向的东西。在C++语言编程时不要弄乱原始指针。从上个千年开始就是这样。请走向当代。@πάνταῥεῖ 我在上一个问题中也有类似的评论,我将作出相应的回应。我是C++新手和指针的概念,想学习下引擎盖是什么。嗯,我看不出这有什么害处:)@Astaboom“我看不出这有什么害处:)”嗯,你自己在各个方面都很容易出错。祝你旅途愉快。(顺便说一句,Chuck Norris会使用整数值和c风格的强制转换来来回指针来完成这项工作)。@πάνταῥεῖ 一旦我有能力编写自己的程序,我会记住你的建议。谢谢他们的意思是你传递一个指针的副本,而不是它指向的东西。不要弄乱r