C++使用指向对象的指针

一、使用new初始化对象

通常,如果Class_name是类,value的类型为Type_name,则下面的语句:

Class_name *pclass = new Class_name(value);

将调用如下的构造函数:

Class_name(Type_name);

这里会有一些琐碎的转换,如:

Class_name(const Type_name &);

另外,如果不存在二义性,则将发生由原型匹配导致的转换(如int转为double)。

下面的初始化方式将调用默认构造函数:

Class_name *pclass = new Class_name;

二、随机数

插入一条随机数的使用:

// 使用srand() rand() time()
#include <ctime>
#include <cstdlib>

int a = 9;
srand(time(0));
int b = rand() % a;

三、再谈new与delete

根据下面使用,进行说明:

// 这不是new为要存储的字符串分配内存,而是为对象分配内存,也就是说为String类的成员变量分配内存。
String *str = new String("Hello World");

再看一个示例说明程序运行阶段的内存释放情况:

class Act 
{
    // 声明的变量与方法
    ...
};

Act nice;	// 外部对象

int main()
{
    Act *pt = new Act;	// 动态对象
    {
        Act act;        // 自动对象(局部变量)
        ...
    }	// 执行到定义的代码块末尾时,将自动调用对应act对象的析构函数
    
    delete pt;    // 对指针pt应用delete运算符时,将调用动态对象*pt的析构函数
    ...
}    // 整个程序运行结束时,将调用静态对象nice的析构函数

在以下几种情况下析构函数将被调用:

(1)如果对象是动态变量,则当执行完定义该对象的程序块时,将调用该对象的析构函数。

(2)如果对象是静态变量(外部变量、静态变量、静态外部变量或来自名称空间),则在程序结束时将调用对象的析构函数。

(3)如果对象是用new创建的,则仅当显式使用delete删除对象时,该对象的析构函数才被调用。

四、指针和对象小结

使用对象指针时,需要注意以下几点:

(1)使用常规表示法来声明指向对象的指针:

String *ptr;

(2)可以将指针初始化为指向已有的对象:

String str = "Hello World";
String *ptr = &str;

(3)可以使用new来初始化指针,这将创建一个新对象:

String str = "Hello World";
String *ptr = new String(str);

(4)对类使用new将调用相应的类构造函数来初始化新创建的对象:

// 调用默认构造函数
String *ptr = new String;

// 调用String(const char *)构造函数
String *ptr = new String("Test");

// 调用复制构造函数
String *ptr = new String(str);

(5)可以使用->运算符通过指针访问类方法:

String *ptr = new String;
String *pst = new String;

if (ptr->length() < pst->length())

(6)可以对对象指针应用解除引用运算符(*)来获得对象:

if (str < *ptr)
    ptr = &str;

五、再谈定位new运算符

定位new运算符可以在分配内存时指定分配的内存位置,根据以下代码实例进行分析说明:

const int BUF = 512;

class JustTesting
{
private:
    std::string words;
    int number;
public:
    JustTesting(const std::string & s = "Just Testing", int n = 0);
    ~JustTesting();
    void Show() const;
};

int main()
{
    // 使用new运算符创建一个512字节的内存缓冲区
    char* buffer = new char[BUF];
    JustTesting *pc1, *pc2;

    // 使用定位new运算符在内存缓冲区创建对象
    pc1 = new (buffer) JustTesting;
    // 使用new在堆上创建对象
    pc2 = new JustTesting("Heap1", 20);

    std::cout << "Memory block address:\n" << "buffer: "
              << (void*)buffer << "    heap:" << pc2
              << std::endl;
    std::cout << "Memory contents:\n";
    std::cout << pc1 << ": ";
    pc1->Show();
    std::cout << pc2 << ": ";
    pc2->Show();

    JustTesting *pc3, *pc4;
    pc3 = new (buffer) JustTesting("Bad Idea", 6);
    pc4 = new JustTesting("Heap2", 10);

    std::cout << "Memory contents:\n";
    std::cout << pc3 << ": ";
    pc3->Show();
    std::cout << pc4 << ": ";
    pc4->Show();

    delete pc2;
    delete pc4;
    delete [] buffer;
}

上述代码示例存在的问题:

(1)使用定位new运算符创建第二个对象时,将使用一个新对象来覆盖用于第一个对象的内存单元。显然,如果类动态的为其成员分配内存,这将引发问题。

(2)将delete应用于pc2和pc4,将自动调用pc2和pc4指向的对象的析构函数,然而 ,将delete[]应用于buffer时,不会为使用定位new运算符创建的对象调用析构函数。原因在于delete可与常规new运算符配合使用,但不能与定位new运算符配合使用。

解决定位new运算符创建的对象的内存释放方案:

显式的为使用定位new运算符创建的对象调用析构函数,这是需要显式调用析构函数的情形之一。显式的调用析构函数时,必须指定要销毁的对象,由于有指向对象的指针,因此可以使用这些指针,使用如下示例:

pc3->~JustTesting();
pc1->~JustTesting();

delete[] buffer;

使用定位new运算符创建的对象显式调用析构函数需注意以下事项:

(1)对于使用定位new运算符创建的对象,应以与创建顺序相反的顺序进行删除(先创建后释放)。原因在于,晚创建的对象可能依赖于早创建的对象。

(2)仅当所有对象都被销毁后,才能释放用于存储这些对象的缓冲区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值