简体   繁体   中英

Return by reference in C++ - Reference assignment vs value assignment

Suppose I have:

    class SomeObject {

    };

    SomeObject& f() {
        SomeObject *s = new SomeObject();
        return *s;
    }

    // Variant 1
    int main() {
        SomeObject& s = f();
        // Do something with s
    }

   // Variant 2
    int main() {
        SomeObject s = f();
        // Do something with s
    }

Is there any difference between the first variant and the second? any cases I would use one over the other?

Edit: One more question, what does s contain in both cases?

First, you never want to return a reference to an object which was dynamically allocated in the function. This is a memory leak waiting to happen.

Beyond that, it depends on the semantics of the object, and what you are doing. Using the reference (variant 1) allows modification of the object it refers to, so that some other function will see the modified value. Declaring a value (variant 2) means that you have your own local copy, and any modifications, etc. will be to it, and not to the object referred to in the function return.

Typically, if a function returns a reference to a non-const, it's because it expects the value to be modified; a typical example would be something like std::vector<>::operator[] , where an expression like:

v[i] = 42;

is expected to modify the element in the vector. If this is not the case, then the function should return a value, not a reference (and you should almost never use such a function to initialize a local reference). And of course, this only makes sense if you return a reference to something that is accessible elsewhere; either a global variable or (far more likely) data owned by the class of which the function is a member.

In the first variant you attach a reference directly to a dynamically allocated object. This is a rather unorthodox way to own dynamic memory (a pointer would be better suited for that purpose), but still it gives you the opportunity to properly deallocate that object. Ie at the end of your first main you can do

delete &s;

In the second variant you lose the reference, ie you lose the only link to that dynamically allocated object. The object becomes a memory leak.

Again, owning a dynamically allocated object through a reference does not strike me as a good practice. It is usually better to use a pointer or a smart pointer for that purpose. For that reason, both of your variants are flawed, even though the first one is formally redeemable.

Variant 1 will copy the address of the object and will be fast

Variant 2 will copy the whole object and will be slow (as already pointed out in Variant2 you cant delete the object which you created by calling new)

for the edit: Both f contain the same Object

None of the two options you asked about is very good. In this particular case you should use shared_ptr or unique_ptr , or auto_ptr if you use older C++ compilers, and change the function so it returns pointer, not reference. Another good option is returning the object by value, especially if the object is small and cheap to construct.

Modification to return the object by value:

SomeObject f() { return SomeObject(); }

SomeObject s(f());

Simple, clean, safe - no memory leaking here.

Using unique_ptr :

SomeObject* f() { return new SomeObject(); }

unique_ptr<SomeObject> s(f());

One of the advantages of using a unique_ptr or shared_ptr here is that you can change your function f at some point to return objects of a class derived from SomeObject and none of your client code will need to be changed - just make sure the base class ( SomeObject ) has a virtual constructor.

Why the options you were considering are not very good:

Variant 1:

SomeObject& s = f();

How are you going to destroy the object? You will need address of the object to call it's destructor anyway, so at some point you would need to dereference the object that s refers to ( &s )

Variant 2. You have a leak here and not a chance to call destructor of the object returned from your function.

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