2013-05-24 2 views
1

Как удалить пространство, которое я выделил, когда мне нужно вернуть результат. Я использовал это, поэтому, если я не нахожу объект, я возвращаю объект с фиктивным контрольным значением.C++ delete object create with new при необходимости для возврата

ClassObject* ClassObjectTwo::find(string findid) { 
     ClassObject *sendback; 
     bool found; 

     for(vector<ClassObject>::iterator it = data.begin(); it != data.end(); it++) { 
       if (it->get_id() == findid) { 
         found = true; 
         sendback = &(*it); 
       } 
     } 

     if(!found) { 
       sendback = new ClassObject; 
       sendback->set_key(100); 
     } 

     return sendback; 
} 

Или это не проблема, так как его уничтожают, когда выходят из сферы действия. Единственное другое решение, о котором я могу думать, - разместить объект в конструкторе и удалить его через конструктор. Я просто не хотел добавлять переменную для одной функции.

+1

Используйте оператор 'delete', чтобы избавиться от объектов, выделенных с помощью' new'. –

+1

, если вы его не нашли, верните NULL. –

+0

@Ryan Вообще говоря, если вы выделяете что-то с помощью 'new', оно не будет« выходить за рамки »и не будет автоматически освобождено для вас автоматически. Вы ** должны ** освободить его, используя 'delete'. (Педантизм: возможно, что некоторые классы закодированы так, чтобы позволить объекту автоматически «удалять» самостоятельно - или освобождаться без явного вызова 'delete', но для этого требуется дополнительный код программистом и обычно не рассматривается) , –

ответ

5

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

Однако в этом случае было бы лучше вернуть NULL.

+1

Я бы сказал, что, хотя вполне законно возвращать динамически выделенный объект и позволить вызывающему его удалять, он, однако, не «отлично» :) - это склонность к ошибкам и накладывает ненужную нагрузку на вызывающего абонента. – villintehaspam

+0

Установка его в NULL вместо нежелательного объекта является более чистым! – Ryan

0

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

4

Здесь есть отличная возможность узнать, поэтому я надеюсь, что вы не возражаете, чтобы я немного отклонился от вашего вопроса. Прежде всего, вы должны привыкнуть к тому, чтобы никогда не работать с владением исходными указателями, т. Е. Не выделять объект и удерживать его в необработанном указателе. Необработанным указателем является, например, переменная sendback в вашей функции, которая имеет тип ClassObject *. Под «владением» я имею в виду тот факт, что вы несете ответственность за удаление памяти самостоятельно.

Вместо этого вы должны всегда сохранять собственность объекта в интеллектуальном указателе, если он должен быть динамически распределен. То есть std::unique_ptr или std::shared_ptr с предпочтением unique_ptr, если вам действительно не требуется совместное владение. Если у вас нет компилятора, совместимого с C++ 11, вы можете использовать эквиваленты Boost boost::scoped_ptr и boost::shared_ptr. Поэтому всякий раз, когда вы хотите динамически выделять объект, всегда помещайте его в интеллектуальный указатель - это гарантирует, что объект будет уничтожен, когда интеллектуальный указатель выходит за рамки. Теперь, если вы хотите вернуть динамически созданный объект, верните умный указатель, который удерживает объект. Как правило, если вам нужно написать delete в своем коде, вы, вероятно, должны были бы использовать умный указатель.

Например, чтобы создать новый динамически созданный ClassObject, можно было бы написать:

std::unique_ptr<ClassObject> myObj = std::unique_ptr<ClassObject>(new ClassObject()); 

или даже лучше, использовать авто, чтобы избежать того, чтобы написать тип явно:

auto myObj = std::unique_ptr<ClassObject>(new ClassObject()); 

с с ++ 14, который должен стать:

Использование интеллектуального указателя предотвращает запуск у меня есть потенциальные проблемы с тем, чтобы эти объекты были удалены перед исключениями.

В вашем случае, однако, вам действительно не нужно возвращать объект вообще. Если вы хотите указать, что объекта не найдено, верните NULL (или действительно вы должны использовать C++ 11 nullptr, если он доступен с вашим компилятором). Другой вариант - вернуть итератор к найденному вами объекту или data.end(), если вы не смогли его найти.

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

Другим моментом может быть принятие аргумента функции как const string &, а не только string, чтобы избежать временной копии параметра (что может случиться).

Существует также еще некоторые дискуссии по вопросу удивительно похож на ваш случай использования, если вы посмотрите на блоге Герба Саттер:

http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/

, а также некоторое дальнейшее обсуждение этого вопроса на:

http://herbsutter.com/2013/05/16/gotw-3-solution-using-the-standard-library-or-temporaries-revisited/

Herb Sutter написал ряд замечательных книг по C++ и принимает активное участие в дальнейшем развитии языка C++, так что не воспринимайте мой прист d для этого, возьмите его ... :).

Cheers!

+0

Это хорошее объяснение и большое спасибо за подробный ответ! – Ryan

0

Я не понимаю, почему вы создаете объект, если вы возвращаете объект. На мой взгляд, это не имеет смысла. Вызывающий должен проверить возвращаемое значение, и если он имеет значение null, что-то вроде создания фиктивного объекта. Вы называетесь методом find, и это говорит мне, что контракт заключается в поиске элемента и возврате его или возвращении значения, указывающего на сбой (nullptr). Если вы хотите создать объект в случае, если искомый объект не найден, тогда назовите его first_or_default или что-то подобное, так как это то, что он на самом деле делает.

Смежные вопросы