开发者

create an instance for a pointer in other scopes

开发者 https://www.devze.com 2023-02-02 19:08 出处:网络
I have two methods to create an instance for a pointer. But one of them will fail. class A { public: int num;

I have two methods to create an instance for a pointer. But one of them will fail.

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 <&开发者_JAVA技巧lt; endl;
}

why is testPointer1 wrong?


The syntax is valid, but it doesn't do what you want because testPointer1() is operating on a copy of the pointer, not the actual pointer itself. So when you assign the address to the newly allocated object, it gets assigned to the copy, not to the original a1 pointer.

Because of this, the address is lost and you get a memory leak. Also, since the original a1 pointer was never modified in the first place, you attempted to dereference a null pointer, which is a bad thing.

I'd say testPointer2() is the better way to do it, but if you want testPointer1() to work, try this:

void testPointer1(A*& a)
{
    a = new A();
    a->num = 10;
} 

The parameter type indicates "a reference to a pointer to A." That way, instead of a copy of the pointer being passed, a reference to the original pointer will be passed. A C++ reference is an alias to another object. So whatever you do on the alias, it gets performed on the original object.


Extra notes:

Note that the parentheses in new A(); are actually significant and their presence or absence makes a difference.

Also note that you must manually delete all new'ed objects after you're done with them, or you will get a leak. Typically you would wrap the pointer in its own class and implement RAII or use a smart pointer such as Boost's smart pointers or auto_ptr, for proper memory management and exception safety.

If you're going to set the value of num on initialization, why not create a constructor?

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));
} 


The testPointer1 functions works on a copy of the provided pointer : modifications to a in testPointer1 are not reflected to the caller.

It's exactly like in this simpler example :

void testInt1(int i)
{
    i++;
}

void testInt()
{
    int i = 0;
    testInt1(i);
    // i is still 0
}

If you want the change in testInt1 to be reflected to the caller, you have to pass either a pointer or reference to i (and not just the value of i). The same solution can be applied to your specific case, though one could argue that pointers to pointer and references to pointer are not really a best practice.


Is this homework ?

This seems to be obvious: formal parameters are saved on the stack & restored after method/function call.

then whatever f(type x), manipulating x inside the function/method won't change it's value outside of the function.

even if type is a pointer type.

the only way to make x change inside a function is to tell it is modifiable through references or pointer to type.

in your case : A* a1 =NULL call to your method won't change value of a1 outside of testPointer1 so a1 will still be NULL after the call.

0

精彩评论

暂无评论...
验证码 换一张
取 消