`

new delete 例子

 
阅读更多

http://blog.163.com/liumaohua890413@126/blog/static/35785164201010954850292/

 

最近一直在啃 C++ Primer 中文版第4版,发现 C++中new和delete应用遍布全书,现对其使用作简单总结。在C++中,可以使用new和delete动态创建和释放数组或者单个对象,现在对它们的使用一一道来。

1.创建动态数组
        数组类型的变量有三个重要的限制:数组长度固定不变,在编译时必须知道它的长度,数组只在定义它的块语句中存在。对于动态分配的数组,虽然长度是固定的,但是动态分配的数组不必在编译时知道其长度,可以(通常也是)在运行时才确定数组长度;同时,动态分配的数组一直存在直到程序显示释放为止,这样,我们就可以自己决定数组的存在与否了。
        每个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区(free store)或堆(heap).C++语言使用new和delete在自由存储区中分配存储空间。
        动态分配数组时,只需指定类型和数组长度,不必为数组对象命名,new表达式返回指向新分配数组的第一个元素的指针:
int *pia=new int[10];
        此new表达式分配了一个含有10个int型元素的数组,并返回指向该数组第一个元素的指针。在自由存储区创建的数组对象是没有名字的,程序员只能通过其地址间接地访问堆中的对象。
        动态分配数组时,如果数组元素具有类类型,将使用该类的默认构造函数实现初始化;如果数组元素是内置类型,则无初始化:
string *psa = new string[10];  // 调用string类的默认构造函数依次初始化数组中的每个元素。
int *pis = new int[10];   //无初始化值
        可使用跟在数组长度后面的一对空圆括号,对数组元素作值初始化:
int *pis = new int[10]();  //数组元素都设置为0

        之所以要动态分配数组,往往是由于编译时并不知道数组的长度。C++中允许动态分配空数组:
size_t n = get_size();
int *p = new int[n];
for(int *q=p;q!=p+n;++q)
『/*处理数组元素的相关代码*/』
        在上面的例子中,只有在程序运行时才能确定n的值。如果n的值为0,代码依然正确执行。C++中虽然不允许定义长度为0的数组变量,但是明确指出,调用new动态创建长度为0的数组是合法的。
char *cp = new char[10];
        用new动态创建长度为0的数组时,new返回有效的非零指针,但不能进行解引用,因为它毕竟没有指向任何元素。

2. 动态创建单个对象
         动态创建对象时,只需指定其数据类型,不必为该对象命名,new表达式返回指向新创建对象的指针,我们通过该指针来访问此对象:
int *pi = new int(1024);
string *ps = new string(10, '9');
         在C++中使用直接初始化语法规则初始化动态创建的对象,上面的表达式就使用该语法规则初始化了动态创建的对象。对于类类型的对象,则使用该类类型的构造函数初始化对象。可对动态创建的对象做值初始化,如下所示:
string *ps = new string();
int *pi = new int();
         对于提供了默认构造函数的类类型,没有必要进行值初始化。如果没有显示初始化动态创建的对象,则对于类类型的对象,用该类的默认构造函数初始化,对于内置类型的对象则无初始化。

3. 动态空间的释放
        动态分配的内存最后必须进行释放。如果不需要动态创建的数组,我们必须显示地将其占用的存储空间返还给程序的自由存储区。C++中使用delete [ ]表达式释放指针所指向的数组空间:
delete [ ] pis;
        该语句释放上面所创建的动态int型数组所占有的存储空间。在关键字delete和指针之间的[ ]告诉编译器该指针指向的是自由存储区中的数组,而并非单个对象。对于表达式 
delete pi; 
        该命令释放了pi指向的int型对象所占用的内存空间。删除指针后,该指针变成悬垂指针(dangling pointer).悬垂指针指向曾今存放对象的内存但该对象已经不存在了。悬垂指针往往导致程序错误,而且很难检测出来。一旦删除了指针所指向的对象,立即将指针置为0,这样就非常清楚地表明指针不再指向任何对象

 

========================================================================

一、基本数据类型的动态分配

new和delete已经完全包含malloc和free的功能,并且更强大、方便、安全。使用动态分配内存时不能忘记释放内存,不要忘记出错处理!下面先看new和delete的基本使用方法。

#include <iostream>
using namespace std;

int main ( )
{
    //基本数据类型
    int *i = new int;              //没有初始值
    int *j = new int(100);         //初始值为100
    float *f = new float(3.1415f); //初始值为3.14159
    cout <<"  i = " << *i << endl;
    cout <<"  j = " << *j << endl;
    cout <<"  f = " << *f << endl;

    //数组
    int *iArr = new int[3];
    for (int i=0; i<3; i++) {
        iArr[i] = (i+1)*10;
        cout << i << ": " << iArr[i] << endl;
    }

    //释放内存
    delete i;
    delete j;
    delete f;
    delete []iArr;    //注意数组的删除方法

    return 0;
}

 

二、内存分配时的出错处理

一般有2种处理方法,一是根据指针是否为空来判断,一是用例外出错处理所抛出的“bad_alloc”来处理。

#include <iostream>
#include <new>
using namespace std;

int main ( )
{
    //判断指针是否为NULL
    double *arr = new double[100000];
    if (!arr) {
        cout <<"内存分配出错!" << endl;
        return 1;
    }
    delete []arr;

    //例外出错处理
    try {
        double *p = new double[100000];
        delete []p;
    } catch (bad_alloc xa) {
        cout <<"内存分配出错!" << endl;
        return 1;
    }

    //强制例外时不抛出错误,这时必须要判断指针
    double *ptr = new(nothrow) double[100000];
    if (!ptr) {
        cout <<"内存分配出错!" << endl;
        return 1;
    }
    delete []ptr;

    cout <<"内存分配成功!" << endl;

    return 0;
}

 

三、用new产生类的实例

前面章节已经用了很多了。

#include <iostream>
using namespace std;

class classA {
    int x;
public:
    classA(int x) { this->x = x; }
    int getX() { return x; }
};

int main ( )
{
    classA *p = new classA(200);    //调用构造函数
    if (!p) {
        cout <<"内存分配出错!" << endl;
        return 1;
    }
    cout <<"x = " << p->getX() << endl;
    delete p;    //调用析构函数

    return 0;
}

 

 

 

 

分享到:
评论

相关推荐

    重载new 用法例子

    在多库环境下,特别是在DLL(动态链接库)之间共享数据时,重载`new`和`delete`可以解决跨库内存管理的问题。 在VS2008环境中,创建和使用DLL时,可能会遇到内存分配和释放的不一致性,因为每个DLL可能有自己的内存...

    C++内存管理详解,new,delete的合理使用

    在上述例子中,`delete stringarray;`实际上只会销毁第一个`string`对象,因为它假设`stringarray`是一个指向单一对象的指针,而不是数组。因此,剩余的99个对象不会被正确地析构,导致内存泄漏和潜在的运行时错误。...

    Actionscript中delete关键字例子

    var obj:Object = new Object(); obj.name = "Alice"; obj.age = 30; trace(obj); // 输出:{name:"Alice", age:30} delete obj.name; trace(obj); // 输出:{age:30},name属性已被删除 ``` 在上述代码中,`delete...

    delete的用法

    1. **匹配原则**:`new`和`delete`、`new[]`和`delete[]`必须成对使用,即`new`对应`delete`,`new[]`对应`delete[]`。 2. **避免内存泄漏**:如果忘记释放由`new`或`new[]`分配的内存,会导致内存泄漏。因此,在...

    拨开自定义operator new与operator delete的迷雾.docx

    在这个例子中,`Base`结构体的构造函数会抛出异常,导致匹配的`operator delete(void*, const char*, int)`被调用,释放内存。而在正常情况下,`delete p`会调用`operator delete(void*)`。 总结来说,自定义`...

    C# 键盘钩子例子 可屏蔽Ctrl+Alt+Delete

    【C# 键盘钩子例子 可屏蔽Ctrl+Alt+Delete】 在Windows操作系统中,开发者有时需要对用户的键盘输入进行特殊处理,例如在某些安全软件或者特定应用中,为了防止用户通过`Ctrl+Alt+Delete`组合键退出程序或唤起任务...

    浅析c++中new和delete的用法

    这个例子中,`new int` 分配了一个 `int` 类型的内存单元,然后 `a` 被赋值为这个内存单元的地址。 2. 初始化新建变量: ```cpp int *a = new int(5); // 分配一个int类型的空间,初始化为5,然后将地址赋值给指针a...

    VB 利用DELETE语句删除数据表中的数据

    在这个例子中,你需要替换`表名`为实际的表名,并根据需要添加适当的条件。如果删除操作依赖于某些参数,你可以使用`cmd.Parameters.AddWithValue`来设置这些值。 在使用DELETE语句时,务必谨慎,因为一旦数据被...

    new的解析(全)

    在这个例子中,`new`为`MyUnion`分配内存,你可以根据需要选择存储`int`或`double`。 ### 内存泄漏与delete操作符 与`new`相对应的是`delete`,用于释放由`new`分配的内存。不正确地使用`new`和`delete`可能导致...

    c++中new和delete操作符用法

    在这个例子中,`new int(100)` 为一个 `int` 分配内存并初始化为100,然后通过指针 `ptr` 访问和修改这个值。最后,`delete ptr` 释放内存。 在实际开发中,除了基础的内存分配和释放外,还需要考虑异常安全性和...

    C++之CNoTrackObject类和new delete操作符的重载实例

    在C++编程中,`CNoTrackObject` 类和 `new`、`delete` 操作符的重载是高级主题,涉及到内存管理和对象生命周期的控制。这里我们将详细探讨这些概念。 首先,`CNoTrackObject` 是一个基类,它定义了自定义的内存分配...

    struts2+extjs中File的upload&download;&delete;例子及说明

    FileInputStream fis = new FileInputStream(new File(filePath)); ServletActionContext.getResponse().addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(attachment.getFileName...

    QT父子与QT对象delete

    在这个例子中,`objParent`是`objChild`和`objChild2`的父对象。当我们删除`objParent`时,Qt会自动遍历其子对象链表,并依次销毁`objChild`和`objChild2`,从而确保没有内存泄漏。 **示例2:** 删除子对象的影响 `...

    第六章答案对象的指针、this指针、const、new和delete.pdf

    8. **动态内存管理**:C++中的`new`和`delete`操作符用于动态分配和释放内存。`new`用于为对象分配内存,例如`ClassName* ptr = new ClassName();`,`delete`用于释放内存,如`delete ptr;`。忘记释放内存可能导致...

    LINQ to SQL语句(12)之Delete和使用Attach

    在这个例子中,detachedItem对象被附加到DataContext,然后设置其状态为“已修改”,表明数据库中的相应记录应进行更新。 值得注意的是,如果试图附加一个已经存在于DataContext中的对象,LINQ to SQL可能会抛出...

    用new创建对象和直接定义的区别

    2. **生命周期**:`new`创建的对象由程序员控制释放(如Java和C++需要手动`delete`,C#有垃圾回收机制)。栈对象由编译器自动管理,当离开其作用域时自动销毁。 3. **初始化**:`new`创建的对象通常通过构造函数...

    cpp代码-只能创建栈对象 做法:将operator new/delete设置为私有的

    在这个例子中,尝试使用`new Singleton()`会抛出一个运行时错误,因为`operator new`是私有的。同样,即使成功创建了对象,也无法通过`delete`来正确地释放它,因为`operator delete`也是私有的。这有效地阻止了在堆...

    利用C语言实践OOP,以及new,delete的深入分析

    总的来说,本文通过一个简单的例子展示了如何在C语言中使用结构体和函数指针来实现OOP的模拟,并探讨了如何用C语言的内存管理函数来替代C++中的`new`和`delete`。虽然这种方法不如C++原生的OOP方便,但它提供了一种...

    一个简单的linq to sql例子

    在这个简单的LINQ to SQL例子中,我们将探讨如何使用C#来实现数据库的基本操作。 首先,我们需要包含必要的命名空间,如`System.Linq`和`System.Data.Linq`,它们提供了 LINQ to SQL 所需的类和方法。接下来,我们...

Global site tag (gtag.js) - Google Analytics