欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HOUR 11 Developing Advanced Pointers

程序员文章站 2024-02-29 08:12:16
...

Creadting Objects on the Heap + Deleting Objects

假定定义好了一个Cat类,在Heap上创建Cat的语法为:

Cat *pPointer = new Cat;

此语句调用默认构造函数对其进行实例化。

 

原理:当delete一个指向heap上的object的指针时候,在内存释放之前,将自动调用析构函数。

class SimpleCat
{
  public:
    SimpleCat();
    ~SimpleCat();
    int getAge() const {return itsAge;}
private:
    int itsAge;
};

new出来的类如何访问其成员数据?

考虑上面的这个类,如果使用语句在heap上定义一个object:

SimpleCat *pPointer = new SimpleCat;

如果我们要调用getAge()函数,怎么使用呢?

(*pPointer).getAge();

  是不是有点麻烦呢?这里的括号确保反引用在访问getAge()之前发生。所以C++提供了更简单的方法,让我们完成对堆上的物体的数据访问。这个运算符就是 ->运算符。

pPointer -> getAge();

  使用这个运算符就舒服多了!

 

Member Data on the Heap

就是一个类的数据成员在构造函数或其他函数中allocate,在析构函数中delete。

熟练下面这个例子,一定牢记,有了new 一定有delete

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

class SimpleCat
{
  public:
    SimpleCat();
    ~SimpleCat();

    int getAge() const {return *itsAge;}
    void setAge(int age) { *itsAge = age;}

    int getWeight() const {return *itsWeight;}
    void setWeight(int weight) const {*itsWeight = weight;}
private:
    int *itsAge;
    int *itsWeight;
};

//It is a default constructor
//if there is no parameter
SimpleCat::SimpleCat()
{
    itsAge = new int(2);
    itsWeight = new int(5);
}

SimpleCat::~SimpleCat()
{
    delete itsAge;
    delete itsWeight;
//由于这是析构函数,所以没有必要为这两个指针赋值为nullptr,因为他们在此终结了已经 } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); SimpleCat *Frisky = new SimpleCat; cout << "Frisky is " << Frisky->getAge() << " years old.\n"; Frisky->setAge(5); cout << "Frisky is " << Frisky->getAge() << " years old.\n"; delete Frisky; return a.exec(); }

 注意到:

  • 对类用户(main函数)来说,并不知道两个类的itsAge 和 itsWeight是指向heap上两个int变量的指针。
  • 析构函数中的delete itsAge ; delete itsWeight;这是默认析构函数做不到的,假如不自己定义析构函数,执行了delete Frisky之后,两个指针 *itsAge *itsWeight也随之被删除,但是堆上对应的两块儿内存还在那里,这就必然造成内存泄漏。

 this 指针

没什么说的,好像在运算符重载那里用的挺多的,而且只能用在类定义内部,因为用在外面谁知道你的这个this指的是谁,每个object都有一个隐藏的this指针,例如

return (this -> getAge());

const Pointer

  1. const int *pOne; 指针指向一个const的整型,不可以 *pOne = 3;
  2. int * const pTwo = new int i; 指针是是一个常指针,不可以 pTwo = &age;换句话说,这个指针只能指向heap中的i变量,不能再有别人了。
  3. const int * const pThree; 一个指向常变量的常指针,以上两个都不可以实现

const Pointer 和 const Function

一个指向const object 的指针,通过该指针只能调用该object内的const 函数,例如

#include <QCoreApplication>
#include <iostream>


class Man
{
public:
    int getAge()  {return age;}
  //int getAge() const {return age;}
void setAge(int newAge) { age = newAge;}; Man(); ~Man(); private: int age; }; Man::Man() { age = 8; } Man::~Man() { } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); const Man *bell = new Man; int i = bell->getAge(); // std::cout << bell->getAge() << std::endl;
delete bell;
bell = nullptr; return a.exec(); }

main函数中,涂黄语句定义了一个指向const对象的指针,红色语句通过该指针访问getAge()函数,此时编译器报错,

 “int Man::getAge(void)”: 不能将“this”指针从“const Man”转换为“Man &”

刚刚说过了一个指向const对象的指针只能调用该对象中的const函数,看类定义中,getAge()我忘了写const了,绿色为正确定义方法。

 

我们还可以理解,如果一个对象被限定为const,那么它的隐藏this指针在使用时,只能通过this访问其const成员函数。

 

Summary

指针可以指向基本数据类型,也可以指向object;

object可以在heap上创建,方法是 Man *bell = new Man; new Man 实际上返回的是一个地址,所以左值必须定义指针才可以。

类的数据成员可以定义为指向heap的指针,创建在构造函数中创建: int *age = new int(2); 删除在析构函数中进行: delete age; 调用如 return (*age);