1

I read somewhere if you want to return a local variable via reference do it via smart pointers and the motivation behind this code is exacttly the same i want to return a Test class variable without it copy being created or in other words Return a local variable with reference . But Everytime return statement executes it calls the destructor . Can anybody help me achieveing my goal via smart pointer . Here is my sample code .

#include <iostream>
#include <memory>
#include <unistd.h>


class Test {
public:
    Test() {
        std::cout << "I am the constructor of A \n";
    }

    ~Test() {
        std::cout << "I am the Distructor of A \n";
    }

};


std::unique_ptr<Test> num() {
    Test obj;
    std::unique_ptr<Test> newInt = std::make_unique<Test>(obj);
    return newInt;
};


int main() {
    std::unique_ptr<Test> ptr = num();
    sleep(12);
}
Umar Farooq
  • 418
  • 2
  • 14

3 Answers3

4
1> std::unique_ptr<Test> num() {
2>     Test obj;
3>     std::unique_ptr<Test> newInt = std::make_unique<Test>(obj);
4>     return newInt;
5> };

In line 3 it creates a new Test object and copy-assigns obj to the new object. The destructor is actually called for the obj variable.

In the example you provided, I don't think obj is needed, just one Test object would be fine.

std::unique_ptr<Test> num() {
    std::unique_ptr<Test> newInt = std::make_unique<Test>();
    /* do something with newInt */
    return newInt;
};

Output:

Program returned: 0
Program stdout
I am the constructor of A 
I am the Distructor of A 
Sprite
  • 3,222
  • 1
  • 12
  • 29
  • So we can't return a local variable by reference via return statement? – Umar Farooq Dec 22 '20 at 10:27
  • @UmarFarooq Yes, you can't. As to why, see [C++ Returning reference to local variable](https://stackoverflow.com/a/4643721/13433323). – Sprite Dec 22 '20 at 10:28
1

The destructor of Test is invoked when the function num goes out of scope because there is a local Test instance named obj on the stack, i.e., with automatically handled lifetime. This is the object from which your return value pointee is copy-initialized when you call

std::unique_ptr<Test> newInt = std::make_unique<Test>(obj);
//                                              ^^^^^^^^^^
//                                              results in copy ctor called
return newInt;

You can avoid that by defining your function as

std::unique_ptr<Test> num() {
    std::unique_ptr<Test> newInt = std::make_unique<Test>();
    return newInt;
};

Apart from that, your reasoning is somewhat misguided. You can return an object by value without copying it, based on guaranteed copy elision. In your case, with C++17 enabled, you can also

Test num() {
    return Test{};
};

Test t = num();

even if you explicitly delete the copy ctor of Test:

Test(const Test&) = delete;
lubgr
  • 37,368
  • 3
  • 66
  • 117
0

You are creating local object in num functions, which of course leads to obj's destruction. In your case it leads to two different destructions. The second one happens after main functions exits and uniqie_ptr's destructor kicks in. Try it like that:

#include <iostream>
#include <memory>
#include <unistd.h>


class Test {
public:
    Test() {
        std::cout << "I am the constructor of A \n";
    }

    ~Test() {
        std::cout << "I am the destructor of A \n";
    }

};


std::unique_ptr<Test> num() {
    std::unique_ptr<Test> obj = std::make_unique<Test>();

    // stuff with obj

    return obj;
};


int main() {
    std::unique_ptr<Test> ptr = num();
    sleep(12);
    return 0;
}
Yossarian
  • 13
  • 2