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
- const int *pOne; 指针指向一个const的整型,不可以 *pOne = 3;
- int * const pTwo = new int i; 指针是是一个常指针,不可以 pTwo = &age;换句话说,这个指针只能指向heap中的i变量,不能再有别人了。
- 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);