【问题标题】:How to make a list of class in C++如何在 C++ 中创建类列表
【发布时间】:2012-08-31 14:08:21
【问题描述】:

我的部分任务是创建一个类,其中包含两个其他类的两个列表并创建“大 4”(构造函数、复制构造函数、操作符 =、析构函数)

这就是我所做的:

using namespace std;

class A{...};
class B{...};

class C{
  list<A> a;
  list<B> b;
  public:
    C();
    ~C();
    C(const C& c);
    void operator=(const C& c);
};

C::C(){
  //How to allocate memory for a and b?
}

C::~C(){
  //How to free the memory?
}

C::C(const C& c){
  a=c.a;
  b=c.b;
}

void operator=(const C& c){
  if(&c==this) return;
  // how do I delete a and b?
  a=c.a;
  b=c.b;
}

你能把我不明白的东西清除掉吗(如代码中的 cmets)。如果我没有正确地做任何事情,也可以提出建议?

【问题讨论】:

  • 这是什么liststd::list
  • 不,这不是家庭作业,编辑了帖子 - 是的 std::list。
  • 您能否详细说明您的意思:包含两个其他类的两个列表?这实际上是两个其他类的实例列表吗?每个列表是否需要包含其他两个类的对象,还是只是一种对象的容器?
  • 一个列表包含一个类的实例,另一个列表包含另一个类的实例。 . .

标签: c++ oop list class


【解决方案1】:

由于您使用的是值(std::list 值),因此无事可做。您的构造函数将自动调用std::list 构造函数,它会分配所需的任何资源。您的析构函数将调用 std::list 析构函数,它会释放它所获取的资源。

如果您持有指向列表的指针(即std::list&lt;A&gt; *a;)或指针列表(std::list&lt;A*&gt; a;')或两者兼有(std::list&lt;A*&gt; *a;),您需要一些额外的工作。

【讨论】:

  • 1.但是这些列表中有一个类的实例——列表会自动释放它们吗? 2. operator=呢?没有什么要补充的? 3. 那么C的构造函数和析构函数应该是空的吗?
  • @John: re 1.: 是的,std::list 会自动调用A 析构函数。 re 2/3:你不需要四个中的任何一个:没有构造函数、没有析构函数、没有复制构造函数和没有赋值运算符。这些函数的默认实现将在您的情况下做正确的事情。
  • @John:你不需要 operator=。将为您生成一个默认的,它会做正确的事情。
  • 如果存储指向 AB 的指针 - 例如在您的类外部创建的对象 - 您可以再次使用智能指针消除对 big 4 的需求,例如std::list&lt;std::shared_prt&lt;A&gt; &gt;
  • 并取决于您打算如何搜索/添加到/从容器中删除。 std::vector 可能是比std::list 更好的选择
【解决方案2】:

//a和b如何分配内存?

您不需要自己分配内存。因为你在堆栈上分配你的成员变量。当有人实例化你的类时,它会自动设置。

//如何释放内存?

您不需要自己释放内存。出于同样的原因。当 scop 结束时,您的堆栈变量将被自动释放。

//如何删除a和b?

为什么需要删除 a 和 b ?您正在将数据从其他对象复制到此对象。

【讨论】:

  • 这与是否“在堆栈上”无关。 C 类型的对象可以在静态范围内声明或使用 operator new 创建。
【解决方案3】:

如果你使用 std::list,你的 A 或 B 类应该: 1 可以在栈和堆上分配 2 不能是单例对象。

【讨论】:

  • std::list 中的对象应该安全地支持复制(克隆)。如果我们把一个单例对象输入一个 std::list,那就错了。
【解决方案4】:

您的变量正在使用自动存储类,不需要显式删除。

你的赋值运算符

void operator=(const& C rhs);

不应返回 void。 // 因为这不是内置类型所做的,并且阻止了赋值链接。

例如

int x, y, z;
x = y = z = 0;

看起来你试图用你的评论来实现移动语义

// how do I delete a and b?

您的赋值运算符应该复制状态,或者您应该记录它使用非标准行为。例如移动语义,boost::noncopyable 等等。

【讨论】:

    【解决方案5】:

    随着移动构造器的出现,它现在是六巨头。在这里学习并了解所有细节,您将获得类样板硕士学位。

    #include <list>
    
    class A {};
    class B {};
    
    class C{
      std::list<A> a;
      std::list<B> b;
      public:
        typedef std::list<A>::size_type size_type;
        explicit C(size_type sz =0);
        virtual ~C();
        C(const C& c);
    
        // Specialize external swap. Necessary for assignment operator below,
        // and for ADL (argument-dependant lookup).
        friend void swap(C& first, C& second); 
    
        // Assignment-operator. Note that the argument "other" is passed by value.
        // This is the copy-and-swap idiom (best practice).
        C& operator=(C other);  // NOTE WELL. Passed by value
    
        // move-constructor - construct-and-swap idiom (best practice)
        C(C&& other);
    
    };
    
    C::C(size_type sz) : a(sz), b(sz) {}
    
    C::~C(){}
    
    C::C(const C& c) :a(c.a), b(c.b){}
    
    void swap(C& first, C& second) {
            // enable ADL (best practice)
            using std::swap; 
            swap(first.a, second.a);
            swap(first.b, second.b);
    }
    
    // Assignment-operator. Note that the argument "other" is passed by value.
    // This is the copy-and-swap idiom (best practice).
    C& C::operator=(C other) {
        swap(*this, other); // Uses specialized swap above.
        return *this;
    } 
    
    // move-constructor - construct-and-swap idiom (best practice)
    C::C(C&& other): a(0) , b(0) {
        swap(*this, other);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-26
      • 2016-02-04
      • 1970-01-01
      • 2012-10-27
      • 2010-09-28
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      相关资源
      最近更新 更多