6

什么是复杂对象(具有显式分配的内部数据)的“最小框架”(必要方法),我想将其存储在 STL 容器中,例如<vector>

对于我的假设(复杂对象 Doit 的示例):

#include <vector>
#include <cstring>
using namespace std;
class Doit {
    private:
        char *a;
    public:
        Doit(){a=(char*)malloc(10);}
        ~Doit(){free(a);}
};

int main(){
    vector<Doit> v(10);
}

*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0804b008 ***
Aborted

在 valgrind 中:

malloc/free: 2 allocs, 12 frees, 50 bytes allocated.

更新:

此类对象的最小方法是:(基于 sbi 答案)

class DoIt{
    private:
        char *a;
    public:
        DoIt() { a=new char[10]; }
        ~DoIt() { delete[] a; }
        DoIt(const DoIt& rhs) { a=new char[10]; std::copy(rhs.a,rhs.a+10,a); }
        DoIt& operator=(const DoIt& rhs) { DoIt tmp(rhs); swap(tmp); return *this;}
        void swap(DoIt& rhs) { std::swap(a,rhs.a); }
};

谢谢,sbi,https: //stackoverflow.com/users/140719/sbi

4

3 回答 3

10

请注意,查尔斯完美地回答了您的问题。

无论如何,根据三法则,你的类,有一个析构函数,也应该有一个复制构造函数和一个赋值运算符。

这是我的做法:

class Doit {
    private:
        char *a;
    public:
        Doit()                   : a(new char[10]) {}
        ~Doit()                    {delete[] a;}
        DoIt(const DoIt& rhs)    : a(new char[10]) {std::copy(rhs.a,rhs.a+10,a);}
        void swap(DoIt& rhs)       {std::swap(a,rhs.a);}
        DoIt& operator=(DoIt rhs)  {swap(rhs); return *this;}
};
于 2010-03-23T15:33:45.850 回答
6

您使用的所有类型都必须是CopyConstructibleand Assignable

CopyConstructiblefor a 类型T意味着 ift是 aT或 a const Tthen 表达式T(t)必须产生T与原来的等价物t;t.~T() 必须有效(可访问的析构函数);并且&t必须将地址t作为[const] T*.

Assignable意味着对于 aTtaTu,表达式t = u必须t等同于u并且是 type T&

请注意,所有这些要求都可以通过简单的内置类型和 POD 结构来满足。如果您在析构函数或构造函数中执行任何重要操作,则必须确保复制构造函数和复制赋值运算符保留等价语义。

于 2010-03-23T15:42:55.147 回答
0

所有vector要求是对象是“可赋值的”,这意味着它需要一个复制构造函数、析构函数和赋值运算符,如果你自己不提供它们,它们都是默认生成的。

正如 sbi 所说,如果您需要其中一个功能,那么您可能需要所有功能。在您的情况下,您还需要提供一个复制构造函数和赋值运算符以避免堆损坏。

于 2010-03-23T15:39:22.890 回答