Ваш дизайн должен сделать выбор. Либо вступите во владение и удалите его, либо не вступайте во владение. В любом случае, пользователь должен знать, как использовать вашу функцию. Они должны либо знать, что ваша функция уничтожит изображение (и, возможно, передать свою собственную копию при необходимости), либо они должны достаточно умен, чтобы управлять своими ресурсами.
Как правило, вы не хотите украсть собственность, просто чтобы удалить ее. Так что я бы не удалил что-нибудь. Если кто-то настолько глуп, чтобы потерять способность удалять передаваемое изображение, проблема не в этой функции. Другими словами, вы должны попытаться защититься от Мерфи, но забудьте о защите от Макиавелли.
Тем не менее, использование сырых указателей плохо! Плохой код C ++ отмечен ручным управлением ресурсами и проблемами с ресурсами. Вы должны иметь обертку вокруг изображения, которая удалит изображение в деструкторе. Таким образом, вы не можете никогда утечка, даже если выдается исключение. Предоставьте ему метод reset()
, который отбрасывает его старый ресурс изображения и получает новый.
Звучит так, как будто вы хотите совместно владеть, поэтому вам нужна оболочка с подсчетом ссылок. Затем проблема решается: если кто-то делает «встроенное» выделение, оно будет помещено в общий указатель, а затем автоматически удалено, когда это будет сделано. (И еще лучше иметь конструктор explicit
, чтобы кто-то знал, что он будет делиться ресурсом.)
Это делается с помощью умного указателя под названием shared_ptr
. Boost имеет один, TR1 - один, а C ++ 0x - один. Просто дайте ему пользовательское удаление (которое освобождает изображение), и вы больше никогда не будете беспокоиться об управлении ресурсами.
Это должно быть сделано с всеми ресурсами. Концепция здесь: Управление ресурсами с привязкой к области действия (SBRM); что ресурс управляется автоматически, используя правила жизни автоматических (стековых) переменных. Он известен как оригинальное, но более уродливое имя Ресурс-Приобретение Инициализация (RAII). Проведите небольшое исследование в этой области, и вы обнаружите, что ваш код проще и чище.
Это не может быть сделано без изменения типа параметра. Вы можете изменить его на:
void Foo(myClass*& bar);
Поскольку неконстантная ссылка может быть привязана только к lvalue:
void foo(int*&);
int main(void)
{
int *i = 0;
int j;
foo(i); // well-formed
foo(&j); // ill-formed
foo(new int); // ill-formed
}
Однако это не позволяет принимать адрес lvalue. Конечно, вы можете сделать простое:
int main(void)
{
int j;
int* pj = &j;
foo(pj); // well-formed
}
И это работает. Но я не знаю, почему вы захотите сделать это.
Приведенное выше решение позволит вам изменить аргумент (потому что это ссылка). Если вы хотите использовать const в функции, вы можете создать такую утилиту:
template <typename T>
class require_lvalue
{
public:
require_lvalue(T& pX) :
mX(pX)
{}
const T& get(void) const
{
return mX;
}
operator const T&(void) const
{
return get();
}
private:
// non-copy-assignable
require_lvalue& operator=(const require_lvalue&);
const T& mX;
};
void foo(require_lvalue<int*>);
Тот же результат, за исключением того, что у вас есть const-ссылка в функции.
Обратите внимание, что MSVC имеет ошибку и принимает это:
foo(new int);
в обоих случаях, хотя это не должно быть. (Однако не принимает new int()
.)