C++快速入门--6

new和delete关键字

在C++中提供了new和delete关键字,new用来开辟内存,delete用来释放内存,并且new会自动调用构造函数,delete关键字会自动调用析构函数,与C语言中中malloc和free中不同的是,这个两个函数不会调用构造函数和析构函数。
当不用调用构造函数与析构函数的时候,它们的功能是一样的

    //C语言语法
    int *p = (int *)malloc(sizeof(int));
    *p = 200;
    //C++语法
    int *p2 = new int;
    *p2 = 200;
    delete p2;
    //C++语法中是分配一个内存,并且初始化
    int *p3 = new int(200);
    delete p3;

    //C语言生成一个数组
    int *pArray = (int *)malloc(sizeof(int) * 2);
    p[0] = 1;
    free(p);
    //C++语法分配一个数组
    int *pArray = new int[2];
    pArray[0] = 2;
    delete[] pArray;
    //这种写法不会调用构造函数和析构函数
    Test *pT1 = (Test *)malloc(sizeof(Test));
    free(pT1);

    //new能调用构造函数,delete能自动调用析构函数,作用都是开辟内存和释放内存
    Test *pT2 = new Test(10);
    delete pT2;

所以在C++中如果建议使用new和delete语法,因为在析构的时候,可能要附带析构其他对象,使用delete语法,能更安全。

静态成员属性与函数

如果你希望某个属性可以被所有该类对象共用,那么,你可以定义成静态成员属性,同样的,你还可以在其他类中引用到这个属性

class T{
public:
    static int a;
}
//初始化的时候,一定要在外面初始化,防止重复开辟内存
int T::a = 100;
int main(){
    cout<<T::a<<endl;
    //当然你也可以直接通过某个对象调用到这个属性
    T t;
    cout<<t.a<<endl;
    //你也可以在main函数再次修改T中a的值,这时候,你只需要通过T::a就能引用和修改其值,不过在此之前必须先在T外初始化
    T::a = 200;
    cout<<T::a<<endl;
    return 0;
}

如上讲述如何将一个类的属性设置成静态,你同样可以将一个函数设置成静态成员函数

#include "iostream"
using namespace std;

class T {
public:
    int c;
    static int a;
    static void test() {
        cout << "hello" << endl;
    }
};
int T::a = 1;

int main() {
    T::a = 2;
    cout << T::a << endl;
    T::test();
    system("pause");
    return 0;
}

这里通过T::test();就能直接访问该函数,但是如果你在test()方法中使用非静态成员属性或者函数的时候,编译器就会报错,例如你在test函数中使用c变量,c变量是非静态的,那么既然它的非静态的,它属于某个对象,而如果你在静态函数中引用这个对象,编译器无法识别它属于哪个对象的,除非你通过某个对象引出这个属性,对于非静态成员函数在静态成员函数中使用,也是不允许的,道理和上面一样。

this指针

在C++中,非静态成员属性,静态成员属性,非静态成员函数和静态成员函数,编译器是如何管理它们的,事实上
成员属性–存储于对象中,于struct相同
静态成员变量–存储于全局区中
成员函数–存储于代码块中
静态成员函数–存储于全局区中
通过如上写法,你可能会想到一个问题,既然成员函数并没存储在当前对象,那么我们使用这个对象调用这个函数,并给当前当前对象的成员属性赋值的时候,编译器是如何知道当前是哪个对象,我应该使用这个函数给哪个成员属性赋值呢,事实上,编译器在处理这种情况的时候,会增加一个this指针,然后通过这个指针,指向要赋值对象,再给这个对象赋值,下面用C语言模拟编译器实现面向对象的封装

struct Test{
    int i;
};
void Test_init(Test * this,int i){
    this->i = i;
}
int Test_getI(Test * this){
    return this->i;
}

void Test_Print(){
    printf("This is class Test. \n");
}

Test a;
Test_init(&a,100);
Test_getI(&a);
Test_Print();

如果将以上代码转换成C++实现

class Test{
private:
    int i;
public:
    Test(int i){
        this->i = i;
    }
    int getI(){
        return this->i;
    }
    static void print(){
        printf("This is class Test.\n");
    }
};
Test a(100);
a.getI();
Test::print();

分配使用C++和C实现你会清楚的发现,事实上,只是C++编译器帮助我们省去了this指针这个参数。

将this指向的元素直接返回,那么这时候可以通过*this来获取到这个对象并返回

练习
//Array.h
#pragma once
class Array
{
private:
    int length;
    int * space;
public:
    Array(int length);
    Array(const Array & array);
    int getLength();
    void setData(int index, int value);
    int getData(int index);
    ~Array();
};

//Array.cpp
#include "Array.h"
#include "iostream"



Array::Array(int length)
{
    if (length < 0)length = 0;
    //this->space = (int *)calloc(length, sizeof(int));
    this->space = new int[length];
    this->length = length;
}
Array::Array(const Array & array) {
    //this->space = (int *)calloc(array.length, sizeof(int));
    this->space = new int[array.length];
    this->length = array.length;
    for (int i = 0; i < array.length; i++) {
        (this->space)[i] = array.space[i];
    }
}


int Array::getLength() {
    return this->length;
}

void Array::setData(int index, int value) {
    (this->space)[index] = value;
}

int Array::getData(int index) {
    return (this->space)[index];
}

Array::~Array()
{
    //free(this->space);
    if(this->space)
        delete [] this->space;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值