Какое назначение указателей лучше (C ++) - PullRequest
0 голосов
/ 02 марта 2012

foo.h

#include "class1.h"

class foo{

    private:
        class1* class1ObjectPointer;

    public:
        foo();
        virtual ~foo();

        void foomethod();

}

foo.cpp (ВЕРСИЯ 1)

#include "foo.h"

foo::foo()
{
    this->class1ObjectPointer = new class1();
}


foo::~foo()
{
    if( this->class1ObjectPointer != NULL ){

        delete class1ObjectPointer;
        this->class1ObjectPointer = NULL;
    }
}


foo::foomethod(){

    *(this->class1ObjectPointer) = some_method(); 
    //suppose some method returns an object of class1

}

foo.cpp (ВЕРСИЯ 2)

#include "foo.h"

foo::foo()
{
    this->class1ObjectPointer = NULL;
}


foo::~foo()
{
    if( this->class1ObjectPointer != NULL ){

        delete class1ObjectPointer;
        this->class1ObjectPointer = NULL;
    }
}


foo::foomethod(){

    class1 object;
    object = some_method(); 
    //suppose some method returns an object of class1
    this->class1ObjectPointer = new class1(object); // copy constructor
}

Какое назначение указателей лучше в следующих случаях:

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

Не могли бы вы предложить какой-нибудь другой и лучший способ сделать то, что я делал в этих отрывках?

Ответы [ 3 ]

2 голосов
/ 02 марта 2012

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

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

class foo {
private:
    class1 class1Object;

public:
    // implicit constructors, assignment and destructor are fine
    void foomethod() {class1Object = some_method();}
};

Ваша вторая ситуация не имеет смысла - все объекты определенного класса имеют одинаковый размер.

Если вам действительно нужно хранить указатель(возможно, потому что вам нужен полиморфизм), тогда самый простой способ справиться с ним - это умный указатель:

class foo {
private:
    std::unique_ptr<class1> class1ObjectPointer;

public:
    foo() : class1ObjectPointer(new class1) {}
    // implicit copying and destructor are fine

    foomethod() {*class1ObjectPointer = some_method();}
    // or, if not assignable, class1ObjectPointer.reset(new class1(*some_method()));
};

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

2 голосов
/ 02 марта 2012

экземпляр класса имеет постоянный размер независимо от каких-либо назначений. Если вы назначите переменную-член некоторому указателю, размер экземпляра не изменится. Просто некоторый мусор в памяти (или значение NULL, если вы его инициализировали первым) будет заменен адресом другого выделенного объекта.

0 голосов
/ 02 марта 2012
  1. проверка if ptr != NULL является избыточной перед delete, поскольку она выполняет проверку внутри.

  2. Какой из этих вариантов лучше, зависит от случая. Оба имеют свое применение.

  3. Не используйте указатели здесь вообще. Если вам нужно, используйте std::unique_ptr (требуется C ++ 11) или boost::shared_ptr.

  4. В любом случае члены в конструкторах должны быть инициализированы , а не назначены. То есть напишите это следующим образом:

    foo::foo() : class1ObjectPointer(new class1) { }
    

    Используется список инициализации .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...