C++入門到理解階段二核心篇(1)——c++面向對象概述、內存分析、引用

1.c++內存分區模型

c++程序在運行的過程當中,內存會被劃分爲如下四個分區html

代碼區:程序的全部程序的二進制代碼,包括註釋會被放到此區ios

全局區:存放靜態變量、全局變量、常量(字符串常量和const修飾的常量),此區的數據將在程序結束後由操做系統釋放c++

using namespace std;
//不在任何函數內的變量是全局變量
int a = 10;
int b = 23;

int main() {
	//在某個函數內的變量
	int c = 12;
	cout << (int)&a << endl;
	cout << (int)&b << endl;
	cout << (int)&c << endl;

}

棧區:用於存放局部變量、函數參數等,是由編譯器自動釋放和分配,因此不能讓棧區返回一個地址,程序員

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

int* f() {
	int a = 10;
	return &a;//棧區不要返回地址。局部變量是由編譯器自動釋放和分配
}
int main() {
	
	int* p = f();
	cout << *p;//10 第一次編譯器會作保留
	cout << *p;//不會打印10
}

堆區:存儲對象(使用new操做符,後面會介紹)由程序員分配釋放,若咱們不釋放,程序結束由操做系統釋放編程

c++中經過new關鍵字將數據開闢到堆區數組

#include <iostream>
using namespace std;
int* f() {
	/*
	*1.指針自己也是局部變量,存放在棧長中,可是保存的數據在堆中
	2.new關鍵字開闢一塊堆區,返回的是該數據類型的指針
	*/
	int *a = new int(10);
	return a;
}
int main() {
	int* p = f();
	cout << *p;//10
	cout << *p;//10
	//3.堆區的數據程,序員能夠經過該delete釋放
	delete p;
	//cout << *p;異常
}

 若是是new一個數組app

//new一個數組
int* arr = new int[10];
//釋放一個數組
delete[] arr;

注意函數

代碼區和全局區是程序編譯成exe可執行文件的時候就已經有了,可是棧區和堆區是程序exe文件執行後產生的url

2.爲何劃份內存(內存劃分意義)

將不一樣的數據放在不一樣的區域,賦予不一樣的生命週期,提升編程靈活程度spa

3.引用

使用引用給一個變量起別名

#include <iostream>
using namespace std;

int main() {	
	int a = 10;
	/*1.定義引用的格式  數據類型 &別名=原名
	*2.引用必須要初始化
	*3.引用初始化後,不可更改
	*/
	int& b = a;
	cout << b;//10
}

前面文章中的地址傳遞會修改實參,值傳遞不會修改實參,引用做爲函數參數會修改實參,簡化使用指針修改實參的複雜過程

#include <iostream>
using namespace std;
void swap(int &a,int &b) {
	int temp = a;
	a = b;
	b = temp;
}
int main() {	
	int a = 10;
	int b = 20;
	swap(a,b);
	cout << a;//20
	cout << b;//10
}

 局部變量不能做爲函數的返回值返回

#include <iostream>
using namespace std;
int& f() {
	int a = 10;//棧區中的局部變量在函數執行完後釋放
	return a;
}
int main() {	
	int &a = f();
	cout << a;//10 編譯器保留
	cout << a;//不在是10
}

若是是局部靜態變量,能夠返回

#include <iostream>
using namespace std;
int& f() {
	static int a = 10;//棧區中的局部變量在函數執行完後釋放
	return a;
}
int main() {	
	int &a = f();
	cout << a;//10
	cout << a;//10
}
#include <iostream>
using namespace std;
int& f() {
	static int a = 10;//棧區中的局部變量在函數執行完後釋放
	return a;
}
int main() {	
	int &a = f();
	cout << a;//10
	cout << a;//10
	f() = 100;//若是函數的返回是一個引用,能夠做爲左值
	cout << a;//100
	cout << a;//100
}

引用本質是指針常量

int main() {	
	int a = 1;
	//內部發現是引用,自動轉成指針常量 int * const b=&a;
	int& b = a;
	b = 2;//內部發現是引用,自動轉成*b=20;
	cout << a;//2
	cout << b;//2
}

 常量引用

#include <iostream>
using namespace std;
//使用const修改函數形參,防止誤操做
void f(const int& a) {
	//a = 100;不容許修改
}
int main() {	
	int& b = 1;//引用自己須要一個合法內存空間,因此這行代碼有誤
	int a = 10;
	f(a);
}

 

4.函數相關

前面c++基礎系列有關函數知識有所描述,這裏補充一些函數高級知識

1.c++中函數能夠有默認值

#include <iostream>
using namespace std;
//1.c++中函數能夠有默認值,而且某個位置有了默認值,那麼從這個位置開始左到右都的有默認值
int f(int a, int b = 10,int c=20) {
	return a + b + c;
}
int main() {	
	int a = 10;
	//2.若是函數有默認值,當咱們傳值使用傳遞的值,不傳值使用默認的
	cout<<f(a);//40
	cout << f(a, 20);//50
}
//3.聲明和實現只能有一個有默認參數
int f1(int a, int b = 10);
int f1(int a, int b) {
	return a + b;
}

2.c++函數中能夠有佔位參數用來佔位,調用函數必需填補該位置

#include <iostream>
using namespace std;

//1.只寫一個數據類型就是佔位
void f(int a,int) {
	cout << "test";
}
//2.佔位參數能夠有默認值
void f1(int a, int=10) {
	cout << "test";
}
int main() {	
	int a = 10;
	f(a, 10);//佔位參必須填補
}

3.函數重載

定義:同一個做用域下,兩個函數參數類型不一樣或者參數順序不一樣或者個數不一樣。此時這兩個函數名字能夠相同。提升複用性

#include <iostream>
using namespace std;

void f(int a,int b) {
	cout << "test";
}

void f(int a) {
	cout << "test";
}
int main() {	
	int a = 10;
	f(a, 10);
}

注意:函數返回值不能做爲函數重載的條件

4.引用也可做爲函數重載條件

#include <iostream>
using namespace std;

void f(int &a) {//int &a=10;不合法
	cout << "test";
}

void f(const int &a) {//const int &a=10;合法
	cout << "test111";
}
int main() {	
	int a = 10;
	f(a);//test
	f(10);//test111
}

5.函數重載遇到默認參數須要注意

void f(int a,int b=10) {//int &a=10;不合法
	cout << "test";
}

void f(int a) {//const int &a=10;合法
	cout << "test111";
}
int main() {	
	int a = 10;
	f(a);//報錯,出現二義性
}

相關文章
相關標籤/搜索