Как создать объект внутри функции и вернуть его в main() без деструктора, удалить его в c++?

У меня этот класс:

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;

};

и эта мебельная функция:

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);
}

Я хочу сделать это в основном:

main(){

 foo a, b;
 foo* c;

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

 c = retSumOf(a, b);

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

}

без вызова конструктора (перегруженной) копии!

Есть ли способ в C++ для динамического создания объекта из функции и возврата его адреса?Без конструктора, чтобы удалить его в конце вызова retSumOf()?

7 ответов

Измените функцию следующим образом:

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);
}


Зачем?

Да, вы можете вернуть (умный) указатель, как говорит Джереми, но зачем вы это делаете? Почему вместо этого правильно реализовать функции копирования и перемещения? У вас уже есть конструктор; по правилу пять вы должны реализовать другие четыре функции в любом случае или подавить их.


Есть несколько способов:

Вы можете использовать возвращаемое значение в качестве аргумента:

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

Другим способом является использование оптимизации RVO

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

В-третьих (если вы можете использовать c++ 11), вы можете использовать конструктор и назначение write move, чтобы избежать создания конструктора копирования. Делая это, вы можете оптимизировать ненужную копию членов и просто "переместить" память из одного экземпляра в другой. Вы можете найти больше информации здесь.

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;
}

Наконец, вы можете использовать shared_ptr или другие интеллектуальные указатели (например, 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;
}
</foo></foo>


Вы можете объявить его как статический:

static myClass objName;

или использовать новые (предпочтительные):

myClass* objName = new myClass; 
return objName

Если вы используете второй метод, вам нужно изменить свою функцию, чтобы вернуть указатель, а не объект.


Вы можете вернуть значение из функции в качестве ссылки на foo и сохранить ее в const foo&. Константа-константа продлит срок службы экземпляра foo на срок жизни переменной.

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

РЕДАКТИРОВАТЬ

Оказывается, это не работает: http://ideone.com/WM3bIe


Просто сделайте это

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);
}

и включить оптимизацию компилятора. Поскольку в вашей функции есть только один оператор return, а result является локальным, компилятор создаст его в стеке вместо возвращаемого значения, избегая копирования.

Не нужно беспокоиться об этом. (и да, не нужно называть "двигаться").

Если вы хотите использовать более "функциональный" подход, дайте foo конструктору, который определяет значения элемента и используйте его:

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

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

так что вы можете сделать

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

Это даже имеет смысл, вы можете называть retSumOf только operator+ и иметь c = a+b;

В любом случае избегайте использования c как голого указателя: никогда не будет ясно, кто должен удалить полученный объект. Это должно быть только значение.

Никогда не используйте char * в качестве участника: неясно, кому принадлежат данные после задания или копии. Вместо этого используйте std::string.


Не уверен, что мой ответ прав, но на самом деле он работает все время для меня:

#include <iostream>

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


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


int main()
{
 GetFoo();
 return 0;
}
</iostream>

Обычно я просто перемещаю объект, созданный внутри функции. Просто чтобы я мог избегать указателей как можно больше. В противном случае я бы использовал указатель Smart, но это то, что я обычно делаю.

licensed under cc by-sa 3.0 with attribution.