class abc ;
void getdata(abc **input=NULL);
class abc {
int x ;
public :
void setX(int in) { x = in ; }
int getX() { return x ; }
};
void getdata(abc **input){
abc *ap = new abc;
cout<< "ap ="<<ap <<endl;
ap->setX(10);
input = new abc*;
*input = ap ;
}
int main() {
abc *a1 ;
cout << a1 <<endl ;
getdata(&a1);
cout<< a1 <<endl;
cout<< a1->getX()<<endl;
return 0;
}
它给出了分段错误,意味着a1将变为空
如果我删除 input = new abc * ;它工作正常。
我不明白这个逻辑。
答案 0 :(得分:3)
在第
行getdata(&a1);
您要将a1的地址发送至getdata
它需要该地址才能访问a1
然后在
input = new abc*;
您覆盖该指针。函数getdata
不再“记住”a1
然后在
*input = ap
你正在写那个新的(无用的)地址。
程序到达时
a1->getX()
a1
从未被写入,并且未定义。
答案 1 :(得分:2)
通过添加行input = new abc*;
,您要更改input
的值,而不是input
指向的值,除非您删除该行,否则该值仍为未定义。
答案 2 :(得分:0)
首先input
指向a1
。但是当你input = new abc*;
时,它停止指向a1
。所以删除该行。
void getdata(abc **input) // here input points to a1
{
abc *ap = new abc;
cout<< "ap ="<<ap <<endl;
ap->setX(10);
*input = ap ; // input still points to a1, but value of a1 is changed
// you may think this as a1=ap;
}
答案 3 :(得分:0)
@ user657267是对的,但让我详细说明一下。
abc,在main中声明为abc *a1 ;
,是一个像任何其他变量一样的变量(比如像int)。它定义了一个内存位置,可能是4个字节,它恰好位于函数main的堆栈中。该内存适用于某些数据,在这种情况下恰好是一个地址。
与任何变量一样,变量存储其数据的内存位置也有一个地址。乍一看这可能会让人感到困惑,但它没有什么神奇之处 - 地址也是值,与其他任何地方一样,并且可以存储在变量中,这些变量占据了某个具有自己地址的内存。
将a1的地址传递给要更改变量所持数据的函数是正确的。正确地说,你应用运算符&amp;将地址传递给函数时变量名称为getdata(&a1);
。
getdata()现在知道a1在哪里保存其数据,即在复制到形式参数&#34;输入&#34;的地址。当getdata想要更改该数据时,它需要写入该位置。这是使用运算符*(解除引用运算符)完成的。
现在,a1中的数据恰好是abc对象的(当前可能是无效的)地址。分配给a1的合适数据将是abc对象的地址。例如,使用abc *ap = new abc;
创建的新abc对象的指针ap对于这样的赋值是非常好的值。我们可以在getdata中访问a1,因为我们碰巧在输入中有地址。与通过地址进行的任何分配一样,我们需要使用解除引用运算符*来访问&#34;输入&#34;中的地址 location 。在描述。 (据我们所知,该位置是a1数据所在的位置)。
现在input = new abc*;
做了什么?右侧&#34;新的abc *&#34;,在堆上创建一个可以容纳地址的位置,可能是4字节。它的类型是&#34; abc *&#34;。
运营商&#34; new&#34;返回新创建的对象的地址(即可以将地址保存到abc的4个字节的地址),并将该地址分配给输入。 Oy vey - 我们丢失了主要数据a1存储数据的信息!这就是&#34;输入&#34;一直持续到现在。 &#34;输入&#34;现在指向一个不同的,完全有效的内存位置,它可以保存abc的地址。 *input = ap ;
将在getdata()开头创建的abc的地址写入该内存位置。数据主要人物a1持有的无赖完全没有改变。因为没有任何东西被分配给它,它包含的随机字节很可能继续是一个完全无效的地址。
因此,虽然*input = ap ;
非常好,但它会在错误的位置更改数据。省略覆盖输入所持有的a1数据的完全有效位置,一切都会正常工作。 a1的内容将由getdata()更改,它将新创建的abc对象的地址写入其中,以便取消引用指针,例如,通过a1->getX()
,将是一个有效的操作。
为了避免意外覆盖只读参数,可以将它们声明为const。在这种情况下,getdata(abc **const input)
表示您不想更改值&#34;输入&#34;包含的内容。 (但您仍然可以使用该值来访问a1的数据!)因此,赋值input = new abc*;
会引发编译时错误。