2015-07-21 6 views
1

У меня есть вопрос о хорошем стиле C++: Я хотел бы написать класс «MyClass», в котором есть один или несколько указателей в качестве элементов, и MyClass может выделить память к этим указателям. Я хотел бы использовать неявное представление default-copy-constructor (а также оператор присваивания по умолчанию) для копирования экземпляра MyClass, так что копируются только указатели, а новый объект разделяет данные, которые исходный объект имеет выделены.Помните оригинальный объект, который просто управляет общей памятью

Моя идея состояла в том, чтобы запретить копирование объектов (созданных с помощью конструктора копирования или оператора присваивания) для освобождения памяти (а также выделения памяти указателям на элементы). Для того, чтобы distinguesh между скопированными объектами и исходными объектами (созданного конструктором), я хочу использовать следующий код:

class MyClass 
{ 
public: 
     MyClass(): originalPtr(this) { data = new char[100000]; } 
     ~MyClass() { if(originalPtr == this) delete[] data; } 
private: 
     MyClass *originalPtr; 
     char *data; // shared data (not copiable) 
     char otherFeatures[10]; // individual data (copiable) 
}; 

Будет ли это решение (используя сравнение с this -указателем) хороший стилем для таких цель (например, разбор объекта по вызову по значению) или он рискован? Конечно, я предполагаю, что исходный объект живет всегда дольше, чем скопированные объекты.

Спасибо!

+5

Если оригинал всегда живет дольше, чем копии, зачем копировать вообще, а не раздавать ссылки? –

+0

Для предоставления отдельных данных копий (намечено «otherFeatures»). –

+2

Почему бы не использовать 'shared_ptr' или подобное? – Petr

ответ

1

Нет, это плохая идея. Если указатели разделяются несколькими экземплярами, то тот, который должен освободить, должен быть последним, а не оригинальным. Это отличается тем, что оригинал может быть не тем, кто умирает, что приведет к тому, что все остальные будут указывать на мусор. Даже если вы предполагаете, что это последний, кто умирает, вам нужно понять, что внутренняя работа класса не должна опираться на внешние предположения. То есть, у класса нет никаких гарантий того, как его жизненный цикл управляется остальной частью реализации, поэтому он не должен делать предположений.

В этой ситуации вы должны отслеживать ссылки на свои данные. Основная идея состоит в том, чтобы отслеживать, сколько копий класса у вас есть. Как только это число достигнет нуля, вы можете освободить эту память; последний экземпляр только что умер. К счастью для вас, STL already provides such an implementation. Они известны как Smart Pointers. Существуют и другие, такие как std::unique_ptr, что делает обратное, гарантируя, что данные принадлежат только одному экземпляру.

0

Хорошо, если в общем случае, когда исходный объект не умирает наконец. Мне нравится идея просто пересчитывать экземпляры. Например, можно было бы использовать такую ​​концепцию:

class MyClass 
{ 
public: 
    MyClass(): countOfInstances(new int()) 
    { 
     ++*countOfInstances; 
     data = new char[100000]; 
    } 

    ~MyClass() 
    { 
     --*countOfInstances; 
     if(!countOfInstances) 
     { 
      delete[] data; 
      delete countOfInstances; 
     } 
    }  

    MyClass(const MyClass &other) // analogous for the assignment operator 
    { 
     countOfInstances = other.countOfInstances; 
     data = other.data; 
     otherFeatures = other.otherFeatures; 
     ++*countOfInstances; 
    } 

private: 
    int *countOfInstances; 
    char *data; // shared data (not copiable) 
    char otherFeatures; // individual data (copiable) 

};

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

+0

Почему бы не использовать интеллектуальные указатели и не сэкономить? –

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

  • Нет связанных вопросов^_^