функция, которая изменяет объект, на который указывает std :: unique_ptr <T> - PullRequest
2 голосов
/ 07 мая 2011

Где-то в моем коде у меня есть локальный std::unique_ptr<T>. Мне нужно сделать что-то с указанным объектом, и я использую функцию для этого:

std::unique_ptr<T> some_function( std::unique_ptr<T> &t )
{
    // do stuff
    return t;
}

Я вызываю функцию так:

std::unique_ptr<T> some_T_ptr( new T(/*args*/) );
vector_of_finalized_Ts.push_back( std::move(some_function(std::move(some_T_ptr))));

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

Ответы [ 3 ]

4 голосов
/ 07 мая 2011

Все дело в собственности.Вы хотите some_function стать владельцем указателя или нет?Если нет, вы можете просто передать необработанный указатель на some_function.Если вы хотите, чтобы some_function перешел в собственность (и вернул право собственности), тогда он должен принять unique_ptr по значению.В противном случае оператор возврата (который должен быть std::move(t)) будет перемещаться из ссылки неизвестного происхождения.

std::unique_ptr<T> some_function( std::unique_ptr<T> t )
{
    // I own t here and will delete it if an exception happens
    // do stuff
    // I'm transferring ownership back to the caller
    //     (who may or may not accept ownership)
    return std::move(t);
}

vector_of_finalized_Ts.push_back( some_function(std::move(some_T_ptr)));

или:

void some_function( T* t )
{
    // I don't own t and won't delete it if an exception happens
    // do stuff
}

some_function(some_T_ptr.get());
vector_of_finalized_Ts.push_back( std::move(some_T_ptr));

Любой дизайн подходитЭто зависит только от того, какой код должен владеть указателем (особенно если в какой-то момент выдается исключение).

0 голосов
/ 07 мая 2011

Ваша проблема в том, что вы оба берете unique_ptr по ссылке и возвращаете его.Это уникальный указатель - вы рассматриваете его как разделяемый указатель, и у вас остается потерянное значение nullptr в стеке.Если вы взяли его по значению или по ссылке rvalue, вы можете просто вызвать some_function напрямую, и вам не нужно перемещать результат.

std::unique_ptr<T> some_function( std::unique_ptr<T> &&t )
{
    // do stuff
    return t;
}
vector_of_finalized_Ts.push_back( some_function(std::unique_ptr<T>(new T(...))));
0 голосов
/ 07 мая 2011

(Игнорирование несвязанной синтаксической ошибки в вашем коде. См. Мой комментарий выше.)

Что касается вашего фрагмента, ваш код действителен. Детальность ходов - это цена, которую вы платите за использование std::unique_ptr таким образом и за передачу unique_ptr в функцию, а не ссылку на сам объект.

Я полагаю, у вас есть веские причины для того, чтобы some_function взял std::unique_ptr, и, если это так, то, насколько я могу судить, вы не можете добиться большего успеха.

Если у вас нет веских причин, тогда, ваш ответ. :)

Надеюсь, это поможет.

...