简体   繁体   中英

When the return type is a class, what's the name of the pointer to the return value?

An example:


class A  
{  
    ....  
    A func();  
};  

A A::func()  
{  
...  
return something;  
}  

At assembly level, when compiled, the function A::func will actually have two parameters: the first one is the this pointer, and the second one is the address of a temp A object, created by the caller to store the return value.

For example, if we write a.func() , the program will create a temp A object (let's call it t ) in the stack, and pass the address of a as first parameter, the address of t as second parameter, finally call the function func .

Here is my question: in the realization of A::func , we can get the address of a - it's the pointer this ; but do we have a way to get the address of t ? What's its name?

It will be useful to have it if, for example, I would like to do some memory alloc/free before returning the result.

Here is an example of what I want to do:

class A
{
    int * data;
    A func();
};

A A::func()
{
    // here "ret_p" is the pointer to the return value (let's pretend that it exists)  
    ret_p->data = new int[some length];  
    ...  
    return * ret_p;  
}

Of course, I can create a local object in A::func and then return it; but then the program will do a copy between my local object and the temp object created by the caller. Since the caller already created a temp object, I'm hoping that I can save both time and space by just using it directly. Is that possible?

Well this is maybe out of c++, but I'm still hoping...

There is no such a temp A object parameter ( t ) in the stack.

If you call A a1 = a.func(); and return something; inside, the copy constructor will be called, equivalent to this A a1(something); . The a1 and something are different instances.

If you A a1; a1 = a.func(); A a1; a1 = a.func(); and return something; inside, the a1 = something; // (operator =) a1 = something; // (operator =) will be called. The a1 and something are different instances.

If you call A a1 = a.func(); and return A(p1); inside, this is equivalent to A a1(p1); , there is one instance a1 .

If you call a.func(); directly without assigning to a var and return something; inside, nothing happens when return.

If you call a.func(); directly without assigning to a var and return A(p1); inside, a temp object will be constructed and then destroyed immediately.

If you A a1; a1 = a.func(); A a1; a1 = a.func(); and return A(p1); inside, a temp object will be constructed, and then operator= will be called a1 = temp object; and then the temp object will be destroyed.

For your reference.

After all, A a1 = a.func() or A a1; a1 = a.func() A a1; a1 = a.func() , return something; // a var return something; // a var or return A(p1); // call constructor return A(p1); // call constructor will cause different behaviors, I think you can control memory correctly.

The supplying of &a to func is a form of copy elision .

There is no guarantee that will happen at all, and no C++ level access to the implementation.

I don't think you're clear in your own head when you say "I would like to do some memory alloc/free before returning the result", can you give a specific example? Probably everything you need is made possible by copy elision, move operators, and RAII.


Responding to your example, here's how you should do it.

class A
{
    std :: vector <int> data;
    A func();
};

A A::func()
{
    A ret;
    ret .data .assign (some_length, 123); // or whatever;
    return ret;
}

This will probably optimise the way you want automatically due to copy elision. If you think the compiler won't elide the copy, add a move constructor.

A :: A (A && old)
: data (std :: move (old .data))
{
}

std::vector 's move constructor will simply copy the pointer. If you want to know how that works, well here's the homegrown equivalent.

class A
{
    int * data;

    // Allocate
    A (size_t size) : data (new int [size]) {}

    // Free, only if we haven't moved.
    ~ A () {if (data) delete [] data;}

    // Move
    A (A && old) : data (old .data) {old .data = nullptr;}

    A (const A &) = delete; // or implement with a new allocation.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM