点击这里给我发消息 点击这里给我发消息

C语言里的内存问题

添加时间:2013-12-7
    相关阅读: C语言

    一、\"delete p\" 会删去 \"p\" 指针,还是它指到的资料,\"*p\" ?

    该指针指到的资料。\"delete\" 真正的意思是:「删去指针指到的东西」(delete the thing pointed to by)。同样的英文误用也发生在 c 语言的「释放」指标所指向的记忆体(\"free(p)\"真正的意思是:\"free_the_stuff_pointed_to_by(p)\" )。

    二、能 \"free()\" 掉由 \"new\" 配置到的、\"delete\" 掉由 \"malloc()\" 配置到的记忆体吗?

    不行。在同一个程式里,使用 malloc/free 及 new/delete 是完全合法、合理、安全的;但 free 掉由 new 配置到的,或 delete 掉由 malloc 配置到的指标则是不合法、不合理的。


    三、为什麽该用 \"new\" 而不是 malloc() ?

    建构子/解构子、型别安全性、可被覆盖(overridability)。建构子/解构子:和 \"malloc(sizeof(fred))\" 不同,\"new fred()\" 还会去呼叫fred 的建构子。同理,\"delete p\" 会去呼叫 \"*p\" 的解构子。
    型别安全性:malloc() 会传回一个不具型别安全的 \"void*\",而 \"new fred()\" 则会传回正确型态的指标(一个 \"fred*\")。
    可被覆盖:\"new\" 是个可被物件类别覆盖的运算子,而 \"malloc\" 不是以「各个类别」作为覆盖的基准。

    四、为什麽 c++ 不替 \"new\" 及 \"delete\" 搭配个 \"realloc()\" ?

    避免你产生意外。当 realloc() 要拷贝配置区时,它做的是「逐位元 bitwise」的拷贝,这会弄坏大
    部份的 c++ 物件。不过 c++ 的物件应该可以自我拷贝才对:用它们自己的拷贝建构子或设定运算子。

    五、该怎样配置/释放阵列?

    用 new[] 和 delete[] :

    fred* p = new fred[100];
    //...
    delete [] p;

    每当你在 \"new\" 运算式中用了 \"[...]\" 的话,你就 *!*必须*!* 在 \"delete\" 陈述中使用 \"[]\" 。这语法是必要的,因为「指向单一元素的指标」与「指向一个阵列的指标」在语法上并无法区分开来。

    六、万一我忘了将 \"[]\" 用在 \"delete\" 由 \"new fred[n]\" 配置到的阵列,会发生什麽事?

    灾难。这是程式者的--而不是编译器的--责任,去确保 new[] 与 delete[] 的正确配对。若你弄错了,编译器不会产生任何编译期或执行期的错误讯息。堆积(heap)被破坏是最可能的结局,或是更糟的,你的程式会当掉。

    七、成员函数做 \"delete this\" 的动作是合法的(并且是好的)吗?

    只要你小心的话就没事。所谓的「小心」是:
    1) 你得 100% 确定 \"this\" 是由 \"new\" 配置来的(而非 \"new[]\",亦非自订的 \"new\" 版本,一定要是最原始的 \"new\")。
    2) 你得 100% 确定该成员函数是此物件最後一个会去呼叫的。
    3) 做完自杀的动作 (\"delete this;\") 後,你不能再去碰 \"this\" 的物件了,包括资料及运作行为在内。
    4) 做完自杀的动作 (\"delete this;\") 後,你不能再去碰 \"this\" 指标了。换句话说,你不能查看它、将它与其他指标或是 null 相比较、印出其值、对它转型、对它做任何事情。

    很自然的,这项警告也适用於:当 \"this\" 是个指向基底类别的指标,而解构子不是virtual 的场合。

    八、该怎麽用 new 来配置多维阵列?

    有很多方法,端视你对阵列大小的伸缩性之要求而定。极端一点的情形,如果你在编译期就知道所有阵列的维度,你可以静态地配置(就像 c 一样):

    class fred { /*...*/ };

    void manipulatearray()
    {
    fred matrix[10][20];

    //使用 matrix[i][j]...

    //不须特地去释放该阵列
    }

    另一个极端情况,如果你希望该矩阵的每个小块都能不一样大,你可以在自由记忆体里配置之:

    void manipulatearray(unsigned nrows, unsigned ncols[])
    //\'nrows\' 是该阵列之列数。
    //所以合法的列数为 (0, nrows-1) 开区间。
    //\'ncols[r]\' 则是 \'r\' 列的行数 (\'r\' 值域为 [0..nrows-1])。
    {
    fred** matrix = new fred*[nrows];
    for (unsigned r = 0; r < nrows; ++r)
    matrix[r] = new fred[ ncols[r] ];

    //使用 matrix[i][j]...

    //释放就是配置的反动作:
    for (r = nrows; r > 0; --r)
    delete [] matrix[r-1];
    delete [] matrix;
    }

    九、怎样确保某类别的物件都是用 \"new\" 建立的,而非区域或整体/静态变数?

    确定该类别的建构子都是 \"private:\" 的,并定义个 \"friend\" 或 \"static\" 函数,来传回一个指向由 \"new\" 建造出来的物件(把建构子设成 \"protected:\",如果你想要有衍生类别的话)。

    class fred { //只允许 fred 动态配置出来
    public:
    static fred* create() { return new fred(); }
    static fred* create(int i) { return new fred(i); }
    static fred* create(const fred& fred) { return new fred(fred); }
    private:
    fred();
    fred(int i);
    fred(const fred& fred);
    virtual ~fred();
    };

    main()
    {
    fred* p = fred::create(5);
    ...
    delete p;
    }

相关C语言里的内存问题

咨询热线:020-85648757 85648755 85648616 0755-27912581 客服:020-85648756 0755-27912581 业务传真:020-32579052
广州市网景网络科技有限公司 Copyright◎2003-2008 Veelink.com. All Rights Reserved.
广州商务地址:广东省广州市黄埔大道中203号(海景园区)海景花园C栋501室
= 深圳商务地址:深圳市宝源路华丰宝源大厦606
研发中心:广东广州市天河软件园海景园区 粤ICP备05103322号 工商注册