Сведения о вопросе

FELL

14:15, 8th August, 2020

Теги

c++   memory   pointers    

C++ управление памятью

Просмотров: 390   Ответов: 8

Я узнал в колледже, что вы всегда должны освободить свои неиспользуемые объекты, но не то, как вы это делаете на самом деле. Например, правильно структурировать код и так далее. Существуют ли какие-либо общие правила о том, как обрабатывать указатели в C++?

В настоящее время мне запрещено использовать boost. Я должен придерживаться чистого c++, потому что фреймворк, который я использую, запрещает любое использование дженериков.



  Сведения об ответе

прога

01:28, 29th August, 2020

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

  1. Только один объект когда-либо будет владеть указателем. По умолчанию это создатель.
  2. Право собственности может быть передано дальше. Чтобы указать передачу права собственности, объект передается как указатель в сигнатуре метода (например, void Foo (Bar *zonk);).
  3. Владелец будет решать, когда удалить объект.
  4. Чтобы передать объект в метод только для использования, объект передается как ссылка в сигнатуре метода (например, void Foo (Bat &zonk);).
  5. Классы, не являющиеся владельцами, могут хранить ссылки (никогда не указатели) на объекты, которые им даны, только когда они могут быть уверены, что владелец не уничтожит их во время использования.

В принципе, если класс просто использует что-то, он использует ссылку. Если класс владеет чем-то, он использует указатель.

Это работало прекрасно и было приятно использовать. Проблемы с памятью были очень редки.


  Сведения об ответе

JUST___

15:50, 16th August, 2020

Правила:

  1. Везде, где это возможно, используйте интеллектуальный указатель . Boost имеет некоторые лучший из них .
  2. Если ты не могу использовать умный указатель, null out ваш указатель после его удаления .
  3. Никогда не работайте там, где вам не позволят использовать Правило 1.

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


  Сведения об ответе

pumpa

23:03, 16th August, 2020

Я бы добавил Здесь еще одно правило:

  • Не создавайте и не удаляйте объект, когда автоматический объект будет работать просто отлично.

Мы обнаружили, что программисты, которые являются новичками в C++, или программисты, пришедшие из таких языков, как Java, похоже, узнают о новом и затем одержимо используют его всякий раз, когда они хотят создать какой-либо объект, независимо от контекста. Это особенно пагубно, когда объект создается локально внутри функции исключительно для того, чтобы сделать что-то полезное. Использование нового таким образом может негативно сказаться на производительности и может слишком легко привести к глупым утечкам памяти, когда соответствующее удаление будет забыто. Да, интеллектуальные указатели могут помочь с последним, но это не решит проблемы производительности (предполагая, что новый/удалить или эквивалент используется за кулисами). Интересно (ну, может быть), что мы обнаружили, что удаление часто имеет тенденцию быть дороже, чем Новый при использовании Visual C++.

Некоторая путаница также возникает из-за того, что функции, которые они вызывают, могут принимать указатели или даже умные указатели в качестве аргументов (когда ссылки, возможно, будут better/clearer)., это заставляет их думать, что им нужно "create" указатель (многие люди, похоже, думают, что это то, что делает new), чтобы иметь возможность передавать указатель на функцию. Очевидно, что это требует некоторых правил о том, как пишутся APIs, чтобы сделать соглашения о вызовах как можно более однозначными, которые подкрепляются четкими комментариями, поставляемыми с прототипом функции.


  Сведения об ответе

ASER

21:06, 1st October, 2020

В общем случае (управление ресурсами, где ресурс не обязательно является памятью), вы должны быть знакомы с шаблоном RAII . Это одна из самых важных частей информации для разработчиков C++.


  Сведения об ответе

PAGE

08:44, 7th August, 2020

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

Иногда вам нужно выделить объекты динамически, но они будут использоваться только в течение определенного промежутка времени. Например, в предыдущем проекте мне нужно было создать сложное представление в памяти схемы базы данных-в основном сложный циклический граф объектов. Однако граф был нужен только на время соединения с базой данных, после чего все узлы можно было освободить одним выстрелом. В этом случае хороший шаблон для использования-это то, что я называю "local GC idiom.", я не уверен, что у него есть имя "official", так как это то, что я видел только в своем собственном коде и в Cocoa (см. NSAutoreleasePool в справочнике Apple Cocoa).

Короче говоря, вы создаете объект "collector", который сохраняет указатели на временные объекты, выделяемые с помощью new. Он обычно привязан к некоторой области в вашей программе, либо к статической области (например, -- как объект, выделенный стеком, который реализует идиому RAII), либо к динамической (например, -- привязан к времени жизни соединения с базой данных, как в моем предыдущем проекте). Когда объект "collector" освобождается, его деструктор освобождает все объекты, на которые он указывает.

Кроме того, как и DrPizza, я думаю, что ограничение не использовать шаблоны слишком жесткое. Однако, сделав много разработок на древних версиях Solaris, AIX и HP-UX (совсем недавно-да, эти платформы все еще живы в Fortune 50), я могу сказать вам, что если вы действительно заботитесь о переносимости, вы должны использовать шаблоны как можно меньше. Однако использование их для контейнеров и интеллектуальных указателей должно быть в порядке (это сработало для меня). Без шаблонов описанная мною методика более болезненна для реализации. Это потребует, чтобы все объекты, управляемые "collector", производились от общего базового класса.


  Сведения об ответе

JUST___

00:18, 16th August, 2020

Добрый день,

Я бы посоветовал прочитать соответствующие разделы "Effective C++" Скотта Мейерса. Легко читается, и он охватывает некоторые интересные готы, чтобы поймать неосторожных.

Я также заинтригован отсутствием шаблонов. Так что никаких STL или Boost. Вау.

Кстати, заставить людей договориться о конвенциях-отличная идея. Как и заставить всех договориться о конвенциях для OOD. Кстати, в последнем издании Effective C++ нет отличной главы о OOD конвенциях, которая была в первом издании, что очень жаль, например соглашения, такие как публичное виртуальное наследование, всегда моделируют отношение "isa".

Грабить


  Сведения об ответе

park

09:15, 28th August, 2020

  • Когда вы должны использовать управление памятью вручную, убедитесь, что вы вызываете удалить в том же scope/function/class/module, который всегда применяется первым, например:
  • Пусть вызывающий функцию выделяет заполненную ею память, не возвращайте указатели new'Ed.
  • Всегда вызывайте delete в том же exe/dll, что и new in, поскольку в противном случае могут возникнуть проблемы с повреждениями кучи (различные несовместимые библиотеки времени выполнения).


  Сведения об ответе

padenie

04:09, 7th August, 2020

вы можете наследовать все из некоторого базового класса, который реализует интеллектуальный указатель как функциональность (используя методы ref()/unref() и счетчик.

Все точки, выделенные @Timbo, важны при проектировании этого базового класса.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться