我有两种方法为指针创建实例。 但其中一个会失败。
class A {
public:
int num;
};
void testPointer1(A* a){
a = new A();
a->num = 10;
}
A* testPointer2(){
A* a = new A();
a->num = 10;
return a;
}
void testPointer() {
A* a1 = NULL;
testPointer1(a1); // this one fails
//cout << a1->num << endl; // segmentation fault
A* a2 = NULL;
a2 = testPointer2();
cout << a2->num << endl;
}
为什么testPointer1错了?
答案 0 :(得分:6)
语法有效,但由于testPointer1()
正在指针的副本上运行,而不是实际指针本身,因此它无法执行您想要的操作。因此,当您将地址分配给新分配的对象时,它将被分配给副本,而不是原始的a1
指针。
因此,地址丢失并导致内存泄漏。此外,由于原始的a1
指针从未被修改过,所以您试图取消引用空指针,这是一件坏事。
我会说testPointer2()
是更好的方法,但是如果你想让testPointer1()
工作,试试这个:
void testPointer1(A*& a)
{
a = new A();
a->num = 10;
}
参数类型表示“对指向A
的指针的引用”。这样,代替传递指针的副本,将传递原始指针的引用。 C ++引用是另一个对象的别名。因此无论你对别名做什么,它都会在原始对象上执行。
额外说明:
请注意new A();
are actually significant and their presence or absence makes a difference中的括号。
另请注意,完成后必须手动delete
所有new
个ed对象,否则会出现泄漏。通常,您可以将指针包装在自己的类中并实现RAII或使用smart pointer,例如Boost's smart pointers或auto_ptr
,以实现正确的内存管理和异常安全。
如果要在初始化时设置num
的值,为什么不创建构造函数?
class A
{
public:
A(int n) : num(n) {}
int GetNum() const { return num; }
private:
int num;
};
void testPointer1(A*& a)
{
a = new A(10);
}
A* testPointer2()
{
return new A(10);
}
// auto_ptr example, see link in second note above
std::auto_ptr<A> testPointer3()
{
return auto_ptr<A>(new A(10));
}
答案 1 :(得分:2)
testPointer1
函数适用于所提供指针的副本:a
中对testPointer1
的修改不会反映给调用者。
这与这个更简单的例子完全相同:
void testInt1(int i)
{
i++;
}
void testInt()
{
int i = 0;
testInt1(i);
// i is still 0
}
如果您希望将testInt1
中的更改反映给调用者,则必须传递指针或对i
的引用(而不仅仅是值 i
)。相同的解决方案可以应用于您的特定情况,但有人可能会争辩指针指针和指针引用并不是最佳实践。
答案 2 :(得分:-1)
这是家庭作业吗?
这似乎是显而易见的: 形式参数保存在堆栈和&amp;方法/函数调用后恢复。
然后无论f(x型),在函数/方法中操纵x都不会改变函数外的值。
即使type是指针类型。
在函数内部进行x更改的唯一方法是告诉它可以通过引用或指向类型的指针进行修改。
在你的情况下: A * a1 = NULL 调用您的方法不会更改testPointer1之外的a1的值 所以a1在通话后仍然是NULL。