封裝
- 成員變量私有化,提供公共的set,get方法給外界去訪問成員變量;
#include <iostream>
using namespace::std;
struct Person {
private:
int m_age;
public:
void setAge(int age){
this->m_age = age;
}
int getAge(){
return this->m_age;
}
};
int main(int argc, const char * argv[]) {
Person person;
person.setAge(20);
int age = person.getAge();
cout << "person age = " << age << endl;
return 0;
}
-
this是指針,通過(guò)指針訪問結(jié)構(gòu)體的成員,必須用箭頭
內(nèi)存布局
- 每個(gè)應(yīng)用都有自己的獨(dú)立的內(nèi)存空間,其內(nèi)存空間一般都有以下幾個(gè)區(qū)域:
- 代碼區(qū):用于存放代碼;
- 數(shù)據(jù)全局區(qū):用于存放全局變量;
- 棧區(qū):沒調(diào)用一個(gè)函數(shù)就會(huì)給函數(shù)分配一段連續(xù)的棧空間,等函數(shù)調(diào)用完畢后,系統(tǒng)會(huì)自動(dòng)回收這段??臻g;
- 堆空間:需要主動(dòng)區(qū)申請(qǐng)和釋放;
堆空間
- 在程序運(yùn)行過(guò)程中,為了能自由控制內(nèi)存的生命周期,大小,會(huì)經(jīng)常使用堆空間的內(nèi)存;
- 堆空間的申請(qǐng)與釋放:
- malloc / free
- new / delete
- new [ ] / delete [ ]
- 注意點(diǎn):
- 申請(qǐng)堆空間成功后,會(huì)返回那一段堆空間的內(nèi)存地址;
- 申請(qǐng)與釋放必須是一對(duì)一的關(guān)系,否則會(huì)出現(xiàn)內(nèi)存泄漏;
#include <iostream>
using namespace::std;
void test1() {
//申請(qǐng)4個(gè)字節(jié)的堆空間內(nèi)存
int *p = (int *)malloc(4);
*p = 10;
//釋放堆空間內(nèi)存
free(p);
}
void test2() {
//申請(qǐng)4個(gè)字節(jié)的堆空間內(nèi)存
int *p = new int;
*p = 20;
//釋放堆空間內(nèi)存
delete p;
}
void test3(){
//申請(qǐng)4*10個(gè)字節(jié)的堆空間內(nèi)存
int *p1 = (int *)malloc(sizeof(int) * 10);
p1[0] = 10;
p1[1] = 10;
p1[2] = 10;
p1[3] = 10;
//釋放
free(p1);
//申請(qǐng)4*10個(gè)字節(jié)的堆空間內(nèi)存
int *p2 = new int[10];
//釋放
delete [] p2;
}
int main(int argc, const char * argv[]) {
test1();
test2();
test3();
return 0;
}
堆空間的初始化
#include <iostream>
using namespace::std;
void test4() {
int size = sizeof(int);
//申請(qǐng)4個(gè)字節(jié)的堆空間內(nèi)存
int *p = (int *)malloc(size);
//從p開始的4個(gè)字節(jié)都存放0
memset(p, 0, size);
cout << *p << endl;
}
void test5(){
//未初始化
int *p1 = new int;
//初始化為0
int *p2 = new int();
//初始化為5
int *p3 = new int(5);
//數(shù)組元素未被初始化
int *p4 = new int[3];
//3個(gè)數(shù)組元素都被初始化為0
int *p5 = new int[3]();
//3個(gè)數(shù)組元素都被初始化為0
int *p6 = new int[3]{};
//數(shù)組首元素被初始化為5,其他元素被初始化為0
int *p7 = new int[3]{5};
}
int main(int argc, const char * argv[]) {
test4();
test5();
return 0;
}
-
memset函數(shù),主要用來(lái)給堆空間內(nèi)存初始化,賦值的;且可以實(shí)現(xiàn)將較大的數(shù)據(jù)結(jié)構(gòu)(結(jié)構(gòu)體,數(shù)組)的內(nèi)存快速清零;
對(duì)象的內(nèi)存
- C++中對(duì)象的內(nèi)存可以存在于三種內(nèi)存區(qū)域;
- 棧區(qū):函數(shù)里面的局部變量;
- 全局區(qū):全局變量;
- 堆區(qū):動(dòng)態(tài)申請(qǐng)堆內(nèi)存(malloc / new)
#include <iostream>
using namespace::std;
struct Person {
private:
int m_age;
public:
void setAge(int age){
this->m_age = age;
}
int getAge(){
return this->m_age;
}
};
//全局區(qū)內(nèi)存
Person g_p1;
int main(int argc, const char * argv[]) {
//棧區(qū)內(nèi)存
Person person;
//堆區(qū)內(nèi)存
Person *p = new Person();
return 0;
}
構(gòu)造函數(shù)
- 構(gòu)造函數(shù)也叫做構(gòu)造器,在對(duì)象創(chuàng)建的時(shí)候自動(dòng)調(diào)用,一般用于完成對(duì)象的初始化操作;
- 其特點(diǎn)有如下:
- 函數(shù)名于類名相同,無(wú)返回值,可以有參數(shù),可以重載,可以有多個(gè)構(gòu)造函數(shù);
- 一旦自定義構(gòu)造函數(shù),必須用其中一個(gè)構(gòu)造函數(shù)來(lái)初始化對(duì)象;
- 通過(guò)malloc分配的對(duì)象不會(huì)調(diào)用構(gòu)造函數(shù);
- 在某些特定情況下,編譯器會(huì)為類生成空的無(wú)參的構(gòu)造函數(shù);
#include <iostream>
using namespace::std;
struct Person {
int m_age;
//構(gòu)造函數(shù)的重載
Person() {
cout << "Person()" << endl;
}
Person(int age) {
this->m_age = age;
cout << "Person(int age)" << endl;
}
};
int main(int argc, const char * argv[]) {
//會(huì)調(diào)用構(gòu)造函數(shù)Person()
Person person;
person.m_age = 20;
//會(huì)調(diào)用構(gòu)造函數(shù)Person(int age)
Person person1 = Person(30);
//會(huì)調(diào)用構(gòu)造函數(shù)Person()
Person *p1 = new Person();
//會(huì)調(diào)用構(gòu)造函數(shù)Person(int age)
Person *p2 = new Person(33);
//不會(huì)調(diào)用構(gòu)造函數(shù)
Person *p3 = (Person *)malloc(sizeof(Person));
return 0;
}
構(gòu)造函數(shù)的調(diào)用
#include <iostream>
using namespace::std;
struct Person {
int m_age;
//構(gòu)造函數(shù)的重載
Person() {
//所有成員變量,全部清零
memset(this, 0, sizeof(Person));
cout << "Person()" << endl;
}
Person(int age) {
this->m_age = age;
cout << "Person(int age)" << endl;
}
};
//全局區(qū)
Person g_person1;
//這是個(gè)函數(shù)聲明,不是調(diào)用Person的構(gòu)造函數(shù)
Person g_person2();
Person g_person3(30);
int main(int argc, const char * argv[]) {
//棧區(qū)
Person person1;
//這是個(gè)函數(shù)聲明,不是調(diào)用Person的構(gòu)造函數(shù)
Person person2();
Person person3(31);
//堆區(qū)
Person *p1 = new Person;
Person *p2 = new Person();
Person *p3 = new Person(32);
return 0;
}
- 全局區(qū),調(diào)用兩次構(gòu)造函數(shù);
- 棧區(qū),調(diào)用兩次構(gòu)造函數(shù);
- 堆區(qū),調(diào)用三次構(gòu)造函數(shù);
析構(gòu)函數(shù)
- 析構(gòu)函數(shù)也叫析構(gòu)器,在對(duì)象銷毀的時(shí)候自動(dòng)調(diào)用,一般用于完成對(duì)象的清理工作;
- 析構(gòu)函數(shù)的特點(diǎn):
- 函數(shù)名以
~開頭,與類同名,無(wú)返回值,無(wú)參數(shù),不可以重載,有且只有一個(gè)析構(gòu)函數(shù);
- 通過(guò)
malloc分配的對(duì)象的在free的時(shí)候是不會(huì)調(diào)用析構(gòu)函數(shù)的;
- 構(gòu)造函數(shù)與析構(gòu)函數(shù)都要被聲明為
public,這樣才能被外界正常使用;
#include <iostream>
using namespace::std;
struct Person {
int m_age;
//構(gòu)造函數(shù)
Person() {
cout << "Person()" << endl;
}
//析構(gòu)函數(shù) 回收Person對(duì)象內(nèi)部申請(qǐng)的堆空間car
~Person() {
cout << "~Person()" << endl;
}
};
int main(int argc, const char * argv[]) {
//棧區(qū)person對(duì)象
Person person;
//堆區(qū)person對(duì)象
Person *p = new Person();
delete p;
return 0;
}
- 會(huì)調(diào)用兩次構(gòu)造函數(shù),析構(gòu)函數(shù);
對(duì)象的內(nèi)存管理
#include <iostream>
using namespace::std;
struct Car {
int m_price;
Car() {
cout << "Car()" << endl;
}
~Car() {
cout << "~Car()" << endl;
}
};
struct Person {
int m_age;
Car *car;
//構(gòu)造函數(shù)
Person() {
cout << "Person()" << endl;
car = new Car();
}
//析構(gòu)函數(shù) 回收Person對(duì)象內(nèi)部申請(qǐng)的堆空間car
~Person() {
cout << "~Person()" << endl;
delete this->car;
}
};
int main(int argc, const char * argv[]) {
//堆區(qū)person對(duì)象
Person *p = new Person();
delete p;
return 0;
}
- 堆區(qū)person對(duì)象在銷毀之前,必須要銷毀清理內(nèi)部堆區(qū)對(duì)象car,否則會(huì)產(chǎn)生內(nèi)存泄漏;
聲明與實(shí)現(xiàn)的分離
- 類的聲明放在
.hpp頭文件,類的實(shí)現(xiàn)放在.cpp實(shí)現(xiàn)文件
// Person.hpp
// C++11_聲明與實(shí)現(xiàn)的分離
//
// Created by ljj on 8/12/21.
//
#ifndef Person_hpp
#define Person_hpp
#include <stdio.h>
//聲明
class Person {
int m_age;
public:
Person();
~Person();
void setAge(int age);
int getAge();
};
#endif /* Person_hpp */
// Person.cpp
// C++11_聲明與實(shí)現(xiàn)的分離
//
// Created by ljj on 8/12/21.
//
#include "Person.hpp"
#include <iostream>
using namespace::std;
//實(shí)現(xiàn)
// :: 域運(yùn)算符
Person::Person(){
cout << "Person()" << endl;
}
Person::~Person(){
cout << "~Person()" << endl;
}
void Person::setAge(int age){
this->m_age = age;
}
int Person::getAge(){
return this->m_age;
}
- 最后在
main文件中導(dǎo)入#include "Person.hpp"
// main.cpp
// C++11_聲明與實(shí)現(xiàn)的分離
//
// Created by ljj on 8/12/21.
//
#include <iostream>
#include "Person.hpp"
using namespace::std;
int main(int argc, const char * argv[]) {
{
Person person;
person.setAge(30);
cout << person.getAge() << endl;
}
return 0;
}