《c++入门经典》笔记11

《c++入门经典》笔记11

第十一章 开发高级指针

11.1在堆中创建对象

实际上,类就是对象的类型,对象也是一种变量,所以你可以在堆中创建int型变量,自然也就能创建自定义型变量。

Cat *pCat = new Cat;

这将调用默认构造函数(无参构造函数),每当在堆或栈中创建对象时,都将调用构造函数。

11.2删除对象

对指向堆中对象的指针调用delete时,将调用对象的析构函数,然后释放内存。

程序清单11.1 HeapCreator.cpp

#include <iostream>

class SimpleCat
{
public:
    SimpleCat()
    {
        std::cout << "Constructor called\n";
        itsAge = 1;
    }
    ~SimpleCat()
    {
        std::cout << "Destructor called\n";
    }

private:
    int itsAge;
};

int main()
{
    std::cout << "SimpleCat simpleCat ...\n";
    SimpleCat simpleCat;

    std::cout << "SimpleCat *pRags = new SimpleCat ...\n";
    SimpleCat *pRags = new SimpleCat;

    std::cout << "delete pRags ...\n";
    delete pRags;

    std::cout << "Exiting, watch simpleCat go ...\n";
    return 0;
}

这里最后一个Destructor called是因为main()函数结束时,simpleCat对象不再在作用域中,所以编译器调用其析构函数。

11.3使用指针访问成员

方法一(解引用运算符):

(*pRags).getAge();

方法二(指向运算符->):

pRags->getAge();

程序清单11.2 HeapAccessor.cpp

#include <iostream>

class SimpleCat
{
public:
    SimpleCat()
    {
        itsAge = 2;
    }
    ~SimpleCat()
    {
        std::cout << "Destructor called\n";
    }
    int getAge() const { return itsAge; }
    void setAge(int age) { itsAge = age; }

private:
    int itsAge;
};

int main()
{
    SimpleCat *simpleCat = new SimpleCat;

    std::cout << "simpleCat is " << (*simpleCat).getAge() << " years old"
              << "\n";
    simpleCat->setAge(5);
    std::cout << "simpleCat is " << simpleCat->getAge() << " years old"
              << "\n";

    return 0;
}

11.4堆中的数据成员

类可能有一个或多个数据成员为指针,并指向堆中的对象。可在构造函数或成员函数中分配内存,并在析构函数中释放内存。

程序清单11.3 DataMember.cpp

#include <iostream>

class SimpleCat
{
public:
    SimpleCat()
    {
        itsAge = new int(2);
        itsWeight = new int(5);
    }
    ~SimpleCat()
    {
        delete itsAge;
        delete itsWeight;
    }
    int getAge() const { return *itsAge; }
    void setAge(int age) { *itsAge = age; }
    int getWeight() const { return *itsWeight; }
    void setWeight(int weight) { *itsWeight = weight; }

private:
    int *itsAge;
    int *itsWeight;
};

int main()
{
    SimpleCat *simpleCat = new SimpleCat;

    std::cout << "simpleCat is " << simpleCat->getAge() << " years old"
              << "\n";
    simpleCat->setAge(5);
    std::cout << "simpleCat is " << simpleCat->getAge() << " years old"
              << "\n";

    return 0;
}

11.5this指针

每个类成员函数都有一个隐藏的参数——this指针,它指向用于调用函数的对象。

通常,在成员函数中,无需使用this指针来访问当前对象的成员变量,如果愿意,可以显示地使用this指针。

程序清单11.4 This.cpp

#include <iostream>

class Rectangle
{
private:
    int itsLength;
    int itsWidth;

public:
    Rectangle();
    ~Rectangle();
    void setLength(int length) { this->itsLength = length; }
    int getLength() const { return this->itsLength; }
    void setWidth(int width) { this->itsWidth = width; }
    int getWidth() const { return this->itsWidth; }
};

Rectangle::Rectangle()
{
    itsWidth = 5;
    itsLength = 10;
}

Rectangle::~Rectangle()
{
}

int main()
{
    Rectangle theRect;
    std::cout << "theRect is " << theRect.getLength() << " feet long." << std::endl;
    std::cout << "theRect is " << theRect.getWidth() << " feet wide." << std::endl;
    theRect.setLength(20);
    theRect.setWidth(10);
    std::cout << "theRect is " << theRect.getLength() << " feet long." << std::endl;
    std::cout << "theRect is " << theRect.getWidth() << " feet wide." << std::endl;
    return 0;
}

11.6悬垂指针

悬垂指针又称为野指针或者迷失指针,指的是对指针调用了delete(释放其指向的内存)之后,没有重新赋值(即没有重新初始化)就开始被使用的指针。

实际上上章笔记中delete关键字时就已经提到野指针的危害。所以进行delete之后应该重新new赋值或者设置为nullptr。

11.7const指针

声明指针时,可在类型前、类型后或者两个地方都使用const。

const int *pOne;//指向常量的指针
int * const pTwo;//常量指针
const int * const pThree;//指向常量的常量指针

三条语句意义各不相同,三个指针类型也各不相同。

pOne是指向整型常量的指针,也就是编译器默认它指向的是一个常量(虽然可能不是),所以不能通过这个指针来更改所指向的常量(编译器认为是常量但不一定是)的值,比如*pOne = 5;编译器就会报错。

 int one = 10;
 const int * pOne = &one;
 *pOne = 5;//报错,表达式必须是可修改的左值,但此时*pOne被认为不可修改

pTwo是指向整型的常量指针,可以修改指向的整型变量,但是pTwo不能指向其他变量。

 int two = 20;
 int * const pTwo = &two;
 *pTwo = 15;
 pTwo = &one;//报错,不能指向别的变量

pThree是一个指向整型常量的常量指针,不能修改它指向的值,也不能让它指向其他变量。

	int three = 30;
 const int * const pThree = &three;
 pThree = &one;//报错,不能指向别的变量
 *pThree = 25;//报错,此时*pThree被认为不可修改

完整代码:(注释起来的是报错的)

#include <iostream>

int main()
{
    int one = 10;
    const int * pOne = &one;
//    *pOne = 5;

    int two = 20;
    int * const pTwo = &two;
    *pTwo = 15;
//    pTwo = &one;

    int three = 30;
    const int * const pThree = &three;
//    pThree = &one;
//    *pThree = 25;

    std::cout<<"one: "<<one<<" *pOne: "<<*pOne<<std::endl;
    std::cout<<"two: "<<two<<" *pTwo: "<<*pTwo<<std::endl;
    std::cout<<"three: "<<three<<" *pThree: "<<*pThree<<std::endl;
    return 0;
}

11.8const指针与const成员函数

程序清单11.5 ConstPointer.cpp

#include <iostream>

class Rectangle
{
private:
    int itsLength;
    int itsWidth;

public:
    Rectangle();
    ~Rectangle();
    void setLength(int length) { itsLength = length; }
    int getLength() const { return itsLength; }
    void setWidth(int width) { itsWidth = width; }
    int getWidth() const { return itsWidth; }
};

Rectangle::Rectangle() : itsWidth(5), itsLength(10) //初始化列表
{
}

Rectangle::~Rectangle() {}

int main()
{
    Rectangle *pRect = new Rectangle;
    const Rectangle *pConstRect = new Rectangle; //pConstRect为指向Rectangle常量型对象的指针
    Rectangle *const pConstPtr = new Rectangle;  //pConstPtr为指向Rectangle型对象的常量指针

    std::cout << "pRect width: " << pRect->getWidth() << " feet\n";
    std::cout << "pConstRect width: " << pConstRect->getWidth() << " feet\n";
    std::cout << "pConstPtr width: " << pConstPtr->getWidth() << " feet\n";

    pRect->setWidth(10);
    //pConstRect->setWidth(10);
    pConstPtr->setWidth(10);

    std::cout << "pRect width: " << pRect->getWidth() << " feet\n";
    std::cout << "pConstRect width: " << pConstRect->getWidth() << " feet\n";
    std::cout << "pConstPtr width: " << pConstPtr->getWidth() << " feet\n";

    return 0;
}

posted @ 2020-07-15 19:04  小立哥  阅读(302)  评论(0编辑  收藏  举报