How to make an object inside a function and return it to main() without the destructor delete it in c++?

StackOverflow https://stackoverflow.com/questions/21558360

Pergunta

I have this class:

class foo{

public:
    foo();
    foo(const int& var);
    foo(const foo& var);
    ~foo();

    foo retSumOf(const foo& var1, const foo& var2);

private:
    int a;
    char* x;

};

and this meber function:

foo foo::retSumOf(const foo& var1, const foo& var2){

    //Make somehow a foo object,
    //lets name it 'result'

    result.a = var1.a + var2.a;

    return (result);
}

I want to do this in main:

main(){

    foo a, b;
    foo* c;

    a.a = 1;
    b.a = 2;

    c = retSumOf(a, b);

    cout << "sum =" << c->a;

}

without to invoke the (overloaded) copy constructor!

Is there a way in C++ to create an object dynamically from a function and return his address? Without the constructor to delete it at the end of the invocation of retSumOf()?

Foi útil?

Solução 2

Modify the function as follows:

foo* foo::retSumOf(const foo& var1, const foo& var2){

    //Make somehow a foo object,
    //lets name it 'result'
    foo* result = new foo();

    result->a = var1.a + var2.a;

    return (result);
}

Outras dicas

Why?

Yes, you can return a (smart) pointer, like Jeremy says, but why would you do that? Why not instead correctly implement the copy and move functions? You already have a constructor; by the rule of five you should implement the other four functions anyway, or suppress them.

There are a couple of ways, first:

You can use the return value as an argument:

void foo::computeSumOf(foo & result, const foo& var1, const foo& var2) ...

Another way is to take advantage of the RVO optimization

foo foo::retSumOf(const foo& var1, const foo& var2)
{
    return foo(var1.a + var2.a);
}
//...
foo x = someFoo.retuSomOf(a,b);

Third (if you can use c++ 11) you can use write move constructor and assignment to avoid copy constructor. By doing this you can optimize the unnecessary copy of members and just "move" the memory from one instance to another . You can find more info here.

class foo{
public:
    foo(foo && rValue) { ... };
    foo& operator = (foo && rValue) { ... };
    ...
};
foo foo::retSumOf(const foo& var1, const foo& var2){
    foo result;
    //same code
    return result;
}

Lastly, you can use shared_ptr or other smart pointers (like intrusive_ptr)

std::shared_ptr<foo> foo::retSumOf(const foo& var1, const foo& var2){
    std::shared_ptr<foo> result = new foo;
    result->a = ...
    return result;
}

You could either declare it as static:

static myClass objName;

or use new (preferred):

myClass* objName = new myClass;    
return objName

If you use the second method, you need to modify your function to return a pointer, rather than an object.

You can return the value from the function as a reference to foo and save it in a const foo&. The const-reference will prolong the lifespan of the foo instance to the lifespan of the variable.

foo& foo::retSumOf(const foo& var1, const foo& var2)
...
const foo& c = retSumOf(a, b);

EDIT

Turns out this does not work: http://ideone.com/WM3bIe

Just do this

class foo
{
    ...
    friend foo retSumOf(const foo& var1, const foo& var2);
    ...
};

foo retSumOf(const foo& var1, const foo& var2);
{
    foo result;
    result.a = var1.a + var2.a;

    return (result);
}

and enable compiler optimization. Since there's only one return statement in your function, and result is local, the compiler will create it on the stack in the place of the return value, avoiding the copy.

No need to worry about that. (and yes, no need to call "move").

If you want a more "functional" approach, give to foo a constructor that defines the member values and use accordngly:

class foo
{
  // you existing code andd ...

  foo(int i, const char* s) :a(i), x(s) 
  {}
};

so that you can do

foo retSumOf(const foo& var1, const foo& var2)
{  return foo(var1.a + var1.b, nullptr); }

It it even make sense, you can name retSumOf just operator+ and have c = a+b;

In any case, avoid to have c as a naked pointer: it will never be clear who has to delete the received object. It only needs to be a value.

Don't ever use char* as a member: it is not clear who owns the data after an assignment or a copy. Use std::string instead.

Not sure if my answer is right but it actually seems to work all the time for me:

#include <iostream>

class Foo
{
    public:
        Foo() {std::cout<<"HEY!";}
        ~Foo() {}
};


Foo&& GetFoo()
{
    return std::move(Foo());
}


int main()
{
    GetFoo();
    return 0;
}

I usually just move an object created within a function.. Just so that I can avoid pointers as much as possible.. Otherwise I'd use a Smart pointer but the above is what I normally do.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top