Способы возврата объектов с постоянными членами из функции - PullRequest
0 голосов
/ 09 сентября 2011

Предположим, у вас есть класс с объявленной константой переменной-члена.

class Test
{
public:
    Test(const int const_param) : const_member_(const_param) {}

private:
    const int const_member_;
};

Нам нужна функция, которая будет возвращать экземпляр этого объекта либо как «возвращаемое значение»

Test Foo();  
Test* Foo();     
Test& Foo();

или как «выходной параметр» (то есть указатель, который передается в).

void Foo(Test* test);
void Foo(Test** test); // maybe this is more correct?

Обратите внимание, что эта функция - единственная вещь, которая может создать объект (в приведенном выше примере Foo будет единственной вещью, которая знает значение const_param и может таким образом создать объект Test)

Что было бы лучшим способом сделать что-то подобное? Это вообще возможно?

Ответы [ 3 ]

2 голосов
/ 09 сентября 2011

Вы можете просто возвратить такой объект копией, если у вас нет веских причин избегать такой схемы:

Foo make_foo()
{
  int n = get_mystery_value()
  Foo x(n);
  x.manipulate();
  return x;
}

Если вы предпочитаете обрабатывать объект указателем, используйте std::shared_ptr<Foo> вместо:

std::shared_ptr<Foo> make_foo()
{
  int n = roll_dice();
  auto px = std::make_shared<Foo>(n);
  px->crazy_stuff();
  return px;
};

Или, если вам нужен только один объект-обработчик, используйте std::unique_ptr<Foo>.


Небольшое объяснение: наличие постоянного члена в вашем объекте по существу означает, что сам объект имеет семантику постоянного объекта. Можно копировать константы, но не переназначать их, так что в вашем типичном случае вы можете создать объект этого класса только один раз, а не переназначить его. Конструктор копирования определяется для вас автоматически, поэтому вы можете пойти дальше и сказать:

int main()
{
  Foo x = make_foo();
  Foo y(make_foo());   // same thing

  x.twiddle();
  y.skedaddle();

  // ...
}

Очевидно, что вы не можете и не скажете x = make_foo();, потому что ваш x является семантически постоянной вещью, для которой переназначение не имеет смысла.

0 голосов
/ 09 сентября 2011

Фабричная функция (функция с исключительными правами на создание объектов определенного типа) должна использовать этот тип в качестве своего возврата, а не «возврат по аргументу».

Если вы должны вернуться по аргументу, C ++ не имеет возможности поместить возвращенный объект в стек как временный. Таким образом, новый объект должен быть в куче. Поскольку в этом случае вы хотите вернуть указатель на объект, а не его содержимое, аргумент функции должен быть изменяемым указателем.

Необработанные указатели, как правило, плохие новости, потому что вы должны помнить delete соответственно. Классы интеллектуальных указателей, такие как unique_ptr и shared_ptr, являются лучшей практикой, а auto_ptr более совместим, но сложнее в использовании.

void Foo(unique_ptr< Test > &test) {
    test = new Test;
}
0 голосов
/ 09 сентября 2011

Я только что попробовал следующее, и он работает нормально.

Test* Foo()<br> {<br> Test* x = new Test(5);<br> return x;<br> }

Не думаю, что вам нужно что-то необычное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...