Что я должен знать о памяти в C++?

public abstract class AbstractDao<T> <br>
{

    private final Class<T> persistentClass;


    public AbstractDao()
    {
        this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
}
16
задан cwallenpoole 15 December 2009 в 14:29
поделиться

15 ответов

Вам действительно, действительно нужно прочитать хорошую книгу - честно говоря, изучение C ++ невозможно без нее. Я рекомендую Accelerated C ++ от Koenig & Moo, двух создателей C ++.

24
ответ дан 30 November 2019 в 15:05
поделиться

Вот что часто привлекает студентов: большие, действительно большие объекты, такие как массивы, должны размещаться в динамической памяти (т. Е. С использованием new).

Кроме того, не проходите мимо больших объектов. Передайте указатели, предпочтительные умные указатели, объектам. Копирование больших объектов отнимает много процессорного времени.

Настройка и документирование правил размещения объектов и владения ими. Является ли вызываемый или вызывающий объект владельцем объекта?

Не возвращать ни ссылки на локальные объекты, ни указатели на локальные объекты.

1
ответ дан 30 November 2019 в 15:05
поделиться

В других языках вы уже должны отслеживать соединения с базой данных, дескрипторы окон, сокеты и т. Д. С помощью таких механизмов, как «наконец» (в Java) или «использование» (в C #). В C ++ просто добавьте память в этот список. Это не концептуально отличается.

2
ответ дан 30 November 2019 в 15:05
поделиться

Во-первых, вы должны понять концепции стека и кучи .

После вы поймете эти понятия, приступайте к изучению языковых конструкций.

5
ответ дан 30 November 2019 в 15:05
поделиться

Как я » Изучая C ++, я обнаружил, что использование инструмента анализа памяти, такого как Valgrind , незаменимо при поиске утечек памяти. Когда вы запускаете свою программу (скомпилированную с отладочными символами) из Valgrind, она определяет строки, в которых выделяется память, но никогда не освобождается позже.

0
ответ дан 30 November 2019 в 15:05
поделиться

new и delete - два наиболее важных ключевых слова для управления памятью. В самом простом случае вам просто нужно не забыть вызывать delete для каждого объекта, который вы вызываете new . Поэтому, если вы вызываете new в цикле, вам нужно убедиться, что вы вызываете delete для каждого из этих новых объединенных объектов. Вам не нужно делать это из цикла, если вы сохраняете где-нибудь копию каждого указателя, которую можно будет удалить позже.

malloc , free , calloc и realloc , вероятно, более продвинуты, чем то, о чем вам нужно беспокоиться. Я думаю, просто запомните, что они есть, если стандартный новый / delete когда-либо будет ощущаться ограничивающим.

0
ответ дан 30 November 2019 в 15:05
поделиться

Ух ты, с этим надо много работать.

Самое главное - быть постоянно прилежным и дисциплинированным. Это верно для любого ресурса на любом языке, даже на более безопасном управляемом языке. Люди чувствуют, что когда язык управляет их памятью, им не нужно об этом думать. Но всегда лучше освобождать любые ресурсы как можно быстрее после того, как вы закончите с ними. Я всегда чувствовал, что «Сборка мусора» в последние годы сделала программистов ленивыми.

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

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

пример:

char* myusedmemory;

myusedmemory = (char *)malloc(1000);  // allocate memory

free(myusedmemory);  //  immediately deallocate memory

/*  go back and fill in the code between */

Есть много хороших ссылок для получения дополнительных знаний по этому вопросу. Я обнаружил, что просмотр руководств на relisoft.com был для меня полезен, хотя основное руководство предназначено для Windows. Еще одну полезную ссылку можно найти здесь.

Что касается различий между указателями и ссылками, одно из основных отличий - гибкость. Вы должны определить ссылку немедленно (int iExample; int & refExample = iExample;) Я бы не подумал, что будет большая разница в производительности. Однако, указатели, являющиеся более мощными и гибкими, будут более опасными и потребуют вышеупомянутой дисциплины для управления.

примеры утечек памяти здесь . но вы можете найти больше, погуглив "утечки памяти в C ++"

Что касается malloc , free , calloc , realloc ], это просто функции, как и любые другие команды, в этих конкретных случаях функции, включенные в stdlib. Вы должны просто понимать, что они делают и как их использовать, как и с любыми другими функциями, например, с обычным printf ().

в качестве примечания: Умные указатели - это очень хороший способ и, как правило, безопаснее.

В качестве еще одного примечания, я хотел бы упомянуть, Code Complete , лучший книга I ' Я читал об управлении ресурсами. Я читал ее от корки до корки много, много раз.

2
ответ дан 30 November 2019 в 15:05
поделиться

Книга под названием «Память как концепция программирования в C и C ++» очень полезна для тех, кто плохо знаком с C / C ++.

3
ответ дан 30 November 2019 в 15:05
поделиться

Вы должны изучить интеллектуальные указатели , они значительно облегчают вашу жизнь, когда дело доходит до управления памятью.

4
ответ дан 30 November 2019 в 15:05
поделиться

Какой минимум мне нужно знать об управлении памятью? (или, где мне найти это)?

Для каждого нового должно быть удаление

Куда мне обратиться за промежуточными и продвинутыми знаниями / учебными пособиями / и т. д. (когда я закончу с основами)?

Прочтите Эффективный C ++ , Более эффективный C ++ и Эффективный STL . Затем google (std: :) auto_ptr, (boost: :) scoped_ptr и (boost: :) shared_ptr

Более конкретно: какова разница в производительности между указателями и ссылками?

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

Я слышал, что в циклах вам нужно убедиться, что вы вызываете delete для любых новых указателей перед цикл повторяется повторно. Это правильно?

Да.

Вам нужно что-то делать со ссылками?

Нет. их - если да, то где?):

Прежде всего, вы никогда не должны удалять указатель malloc ed и никогда освобождать указатель, созданный с помощью новый . Как правило, эти функции не должны появляться в коде C ++. Однако, если вы окажетесь в c-land ...

malloc: аналогично new (выделяет память в куче)
бесплатно: аналогично удалению (свободная память в куче)
calloc: аналогично new + memset (выделяет память в куче, устанавливает ее в ноль)
realloc: пытается изменить размер блока памяти или создает новый блок памяти и копирует старые данные, освобождая старый указатель. Никакого реального эквивалента C ++.

Некоторые полезные элементы памяти можно найти в Google (так оно и написано?) размещение новое

5
ответ дан 30 November 2019 в 15:05
поделиться

Что вам нужно знать об управлении памятью в самом простом смысле, так это то, что вам нужно удалить память, которую вы выделяете в куче. Поэтому при создании объекта типа MyClass * myClass = new MyClass (x); вам необходимо иметь место в вашем коде, которое освобождает / удаляет его с помощью соответствующего delete . На практике это кажется простым, но без надлежащего дизайна и использования вспомогательных объектов, таких как общие указатели, это может быстро стать беспорядочным, особенно когда поддерживается код и добавляются функции. Например, вот классическая утечка памяти:

try
{
    MyClass *myClass = new MyClass(x);

    // Do some stuff can throw an exception

    delete myClass;
}
catch(...)
{
   // Memory leak on exceptions.  Delete is never called
}

ИЛИ еще одна серьезная проблема с управлением памятью вызывает неправильный тип удаления:

int* set = new int[100];
delete set;   // Incorrect - Undefined behavior
// delete [] set;  is the proper way to delete an array of pointers

Обычный способ помочь себе - использовать идиому RAII. ( Распределение ресурсов - это инициализация )

Вот пример использования библиотеки std для предотвращения утечки памяти:

try
{ 
    auto_ptr<MyClass> myClass(new MyClass(x));
    // Now the heap allocated memory associated with myClass
    // will automatically be destroyed when it goes out of scope,
    // but you can use it much like a regular pointer

    myClass->memberFunction();
} 
catch (...)
{

}

Дополнительную информацию о auto_ptr можно найти здесь . Если вы можете использовать C ++ 11, рекомендуется использовать shared_ptr , который часто предпочтительнее auto_ptr.

14
ответ дан 30 November 2019 в 15:05
поделиться

Я искренне рекомендую книгу Программирование коллективного разума для всевозможных интересных алгоритмов и анализа данных в этом направлении.

  • Общие сведения о гарантиях исключений
  • Использование предложения throw

Каковы принципы, которыми руководствуется ваша политика обработки исключений?

Общие способы утечки

Основы

// Every new is matched by a delete.
for(int loop = 0;loop < 10;++loop)
{
    data = new int(5);
}
delete data;
// The problem is that every 'use of' new is not matched by a delete.
// Here we allocate 10 integers but only release the last one.

Необходимо знать

class MyArray
{
    // Use RAII to manage the dynamic array in an exception safe manor.
    public:
        MyArray(int size)
          :data( new int[size])
        {}
        ~MyArray()
        {
            delete [] data;
        }
    // PROBLEM:
    // Ignored the rule of 4.
    // The compiler will generate a copy constructor and assignment operator.
    // These default compiler generated methods just copy the pointer. This will
    // lead to double deletes on the memory.

    private:
        int*   data;
};

Лучшие практики

// Understand what the properties of the smart pointers are:
//
std::vector<std::auto_ptr<int> >   data;

// Will not work. You can't put auto_ptr into a standard container.
// This is because it uses move semantics not copy semantics.

Дополнительно:

// Gurantee that exceptions don't screw up your object:
//
class MyArray
{
   // ... As Above: Plus
   void resize(int newSize)
   {
       delete [] data;
       data = new int[newSize];
       // What happens if this new throws (because there is not enough memory)?
       // You have deleted the old data so the old data so it points at invalid memory.
       // The exception will leave the object in a completely invalid state
   }
15
ответ дан 30 November 2019 в 15:05
поделиться

Из вашего списка вы пропустили new и delete - некоторые говорят, что никогда не следует использовать malloc и бесплатно .

Также часто забывают удалить [] .

2
ответ дан 30 November 2019 в 15:05
поделиться

Все упоминают новые и удаляют, но в большинстве случаев, они не нужны и не должны использоваться эксплицитно:

  • Лучше всего использовать стандартные контейнеры и позволить делать управление памятью.
  • Если это невозможно, используйте умные указатели либо с подсчётом ссылок, либо, в крайнем случае, с более умным сбором мусора.

Конечно, по причинам производительности вы можете захотеть периодически иметь пару new и delete в критическом исполнении, но это должно быть скорее исключением, чем правилом.

.
1
ответ дан 30 November 2019 в 15:05
поделиться

Узнайте о RAII. Некоторые здесь указывали на это, но в то же время объясняли новые/удаленные вещи, не подчеркивая важность РАИИ. С RAII не нужно беспокоиться об управлении памятью.

Люди, новички в Си++, склонны к кодированию, как в Java, везде ставят "новое". Во многих случаях это плохая привычка, в некоторых случаях её нельзя избежать (но по опыту работы над моими проектами это, скорее всего, никогда).

Просто добавление этого комментария, чтобы подчеркнуть это ;) Однако все комментарии совершенно верны

.
1
ответ дан 30 November 2019 в 15:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: