0

In C++11, I have a class with a function that returns a new instance of that class. My clearly incorrect assumption was that if I constructed a new instance and returned it by value, the new instance would stay in scope. But I've learned that what I'm correctly observing is that its being destroyed like any other local variable. EDIT: My question is, what do I need to add or change to make a function instantiate an object and return it (without having it preallocated and passed in as a parameter)?

EDIT2: I've added move and copy constructors, and tried explicitly calling new Thingy instead of just having an instance variable. Still no change in behavior. I see the copy constructor called and then the destructor called when I invoke the function.

template<typename T>
class Thingy {

public:
    // Constructor
    Thingy(unsigned n) {
        n_ = n;
    }

    // Move constructor
    Thingy<T>(Thingy<T> && obj) {
      cout << "Move constructor\n";
      this->n_ = obj.n_;
    }

    // Copy constructor
    Thingy<T>(const Thingy<T>& copy) {
        cout << "Copy constructor\n";
        this->n_ = copy.n_;
    }

    // Destructor
    ~Thingy() {
        cout << "Destructor\n";
    }

    Thingy<T> dosomething() {
        // Thingy<T> thing(n_); <-- this goes out of scope
        Thingy<T>* thing = new Thingy<T>(n_); // I was hoping this would stay in scope, but no
        ...
        return thing;
    }

private:
    unsigned n_;

In my main code I basically do:

Thingy<mytype> mainthing(10);
Thingy<mytype> anotherthing = mainthing.dosomething();

I can see that the destructor is being called and anotherthing is garbage.

What am I doing wrong/missing? Thanks!

Richard Sand
  • 642
  • 6
  • 20
  • 3
    Add a copy constructor and a copy assignment operator so you can observe the copy operations happening as well. Just observing the destructor is only a small fraction of the picture – Silvio Mayolo Sep 03 '22 at 02:44
  • Primitives and objects you allocate on the stack go out of scope when you exit the function. That's what's happening with "Thingy thing(n_);" when you exit "dosomething()": https://courses.engr.illinois.edu/cs225/sp2022/resources/stack-heap/ – paulsm4 Sep 03 '22 at 02:52
  • *"and returned it by value, the new instance would stay in scope."* - Your understanding is incorrect. Further, the provided code will likely exhibit named return value optimization (NRVO) and elision. So in all likelihood there will be two constructs, two destructs, and no actual copies at all. – WhozCraig Sep 03 '22 at 03:35
  • See [Does returning a local variable return a copy and destroy the original(nrvo)?](https://stackoverflow.com/questions/72383114/does-returning-a-local-variable-return-a-copy-and-destroy-the-originalnrvo) and [Shouldn't there be a copy ctor invocation here? Elision disabled (no named return value optimization)](https://stackoverflow.com/questions/72253869/shouldnt-there-be-a-copy-ctor-invocation-here-elision-disabled-no-named-retur). – Jason Sep 03 '22 at 03:50
  • I see lots of deep explanations of why my understanding was wrong, but what IS the correct method? How do I construct an object and return it? Just a simple, prescriptive example similar to the code I pasted so I know "you need to add this and change that" – Richard Sand Sep 03 '22 at 13:55
  • @RichardSand You can use dynamic memory allocation. – Jason Sep 03 '22 at 14:06
  • @RichardSand, you don’t necessarily use dynamic memory allocation. You should define a move constructor, then simply construct an object locally in the function, and simply return it. The move constructor will be invoked. Simple is best. – NicholasM Sep 03 '22 at 14:25
  • @RichardSand You've fallen into quite a deep rabbit hole. There really is no problem that the local Thing you commented out is fine and C++11 cleverness will avoid too much copying. There's a sad tendency of people closing questions as duplicates of questions that are beyond the level of the OP. It's like a 10 year old asks why things fall and telling them to read an undergraduate physics book on gravitation. Sure the answer is there. But it ain't helpful. It isn't the answer that's needed. – Persixty Sep 03 '22 at 18:15
  • @Persixty Totally agree. Its frustrating, I'm basically programming C and avoiding all of the features of C++. I can't overload any operators because I can't create new instances to return. – Richard Sand Sep 03 '22 at 19:26
  • @RichardSand Stack overflow wasn't always like this and there was time when people tried to engage with and help novices were less eager to refer people to answers out of the OPs depth. The short answer is so long as you get the basic idea of copying and destructors you shouldn't be avoiding the features of C++ because you're degenerating into what will look like C in C++ dialect. One day you might get some performance bottleneck and need to reduce some copying. At that point start to read up on copy elision and return-value optimisation. If that's not clear come back to SO. – Persixty Sep 03 '22 at 20:39

0 Answers0