【问题标题】:Which pointer assignment is better (C++)哪个指针分配更好(C++)
【发布时间】:2012-03-02 15:10:31
【问题描述】:

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. class1 的对象始终具有固定大小(例如,其中包含固定变量的类)
  2. class1 的对象可能具有可变大小的成员(例如,其中包含可能具有不同大小的矩阵的类)

你会建议任何其他更好的方法来做我在这些 sn-ps 中所做的事情吗?

【问题讨论】:

  • 你的问题是什么?目前还不清楚你在挣扎什么以及你在问什么。
  • @DavidHeffernan 我需要创建一个class1 的对象,它可以具有可变大小,并且不知道哪种分配空间的方式更好。
  • 代码中被标识为复制构造函数的东西不是复制构造函数。复制构造函数不接受指针。
  • @BenjaminLindley 复制构造函数不会引用要复制的对象作为输入吗?
  • @Matteo:是的,但是通过在对象前面加上&,您提供的是指针,而不是引用。从调用者的角度来看,通过引用获取参数的函数与通过值获取参数的函数没有区别。

标签: c++ pointers memory-management constructor copy-constructor


【解决方案1】:

根据第一个示例重新分配对象可能比分配新对象更好(更有效,更容易避免内存泄漏) - 正如第二个示例中的内存泄漏所证明的那样。

看起来你根本不需要指针;只需在你的类中嵌入一个对象:

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()));
};

如果您真的想自己管理它,那么您需要根据Rule of Three 覆盖默认的复制构造函数和复制赋值运算符,确保在重新分配指针时删除旧对象,并小心异常安全。并且不需要在删除之前检查NULL,也不需要在析构函数中分配NULL

【讨论】:

  • 实际上的问题是class1没有任何方法来设置类的成员,所以当我在实例化之后尝试编辑该类的对象时遇到了一些问题。
【解决方案2】:

无论任何分配如何,类的实例都具有恒定的大小。 如果将成员变量分配给某个指针,则实例的大小不会改变。只是内存中的一些垃圾(或 NULL 值,如果你先初始化它)将被其他分配对象的地址替换。

【讨论】:

  • 这是为什么呢?我认为这取决于它包含的成员变量的大小..
  • @Matteo 但它始终包含相同数量的成员变量,并且它们也始终具有相同的大小。事实上,any 类型的大小是(并​​且必须)在编译时固定的。
  • @Matteo,康拉德鲁道夫是对的。看看:指针,像任何其他变量一样具有固定大小(取决于系统)。并且该指针指向的数据不计入对象的大小,因为它位于内存中的另一个位置。
【解决方案3】:
  1. if ptr != NULL 检查在 delete 前面是多余的,因为它在内部进行检查。

  2. 这些变体中哪个更好取决于具体情况。两者各有千秋。

  3. 这里根本不要使用指针。如果必须,请使用 std::unique_ptr(需要 C++11)或 boost::shared_ptr

  4. 在任何情况下,构造函数中的成员都应该初始化,而不是赋值。也就是这样写:

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

    这使用initialisation list

【讨论】:

  • 如果您不使用 Boost 或 C++11 怎么办?只是好奇。
  • @Almo 那你就是个白痴。 :p 对不起——我的意思是:你的项目协调员就是其中之一。没有理由不使用某些 Boost 组件,shared_ptr 就是其中之一。
  • @KonradRudolph 实际上问题是class1没有任何方法来设置类的成员,所以当我在实例化之后尝试编辑该类的对象时遇到了一些问题.
  • @Almo:即使某些白痴已经取缔了 Boost,你也可能得到了std::tr1::shared_ptr(或std::auto_ptr 作为最后的手段)。
  • @Almo 哇,对不起。也就是说,清除 Boost 许可证虽然肯定是一些工作,但应该是可行且值得的,并且只需完成一次。
猜你喜欢
  • 1970-01-01
  • 2015-03-20
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 1970-01-01
相关资源
最近更新 更多