欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解

 更新時(shí)間:2023年01月04日 08:42:20   作者:一只少年AAA  
這篇文章主要介紹了C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解的相關(guān)資料,需要的朋友可以參考下

命名空間

概述

在C/C++中,變量、函數(shù)和后面要學(xué)到的類都是大量存在的,這些變量、函數(shù)和類的名稱將都存在于全局作用域中,可能會(huì)導(dǎo)致很多沖突。使用命名空間的目的是對(duì)標(biāo)識(shí)符的名稱進(jìn)行本地化,以避免命名沖突或名字污染,namespace關(guān)鍵字的出現(xiàn)就是針對(duì)這種問題的。

舉個(gè)例子:

#include <stdio.h>
#include <stdlib.h>

int rand = 10;

int main()
{
	printf("%d", rand);
	return 0;
}

程序編譯的結(jié)果顯示rand重定義了,為什么會(huì)這樣呢?因?yàn)樵?strong>stdlib.h這個(gè)頭文件中已經(jīng)定義了rand這樣一個(gè)函數(shù),這樣就導(dǎo)致了編譯器不知道這是一個(gè)函數(shù)還是一個(gè)變量,C語言中無法應(yīng)對(duì)這種沖突,只能通過改名字來避免。

而C++為了解決這個(gè)問題,引入了命名空間的概念。

命名空間的定義

定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對(duì){}即可,{}中即為命名空間的成員。

//命名空間
//A就是命名空間的名字
namespace A{
	int a;
	void func()
	{}
}

注意事項(xiàng):

  • 命名空間只能寫在全局
  • 命名空間可以嵌套命名空間
  • 命名空間是開放的,隨時(shí)可以加入新的成員,但是新加入的成員只能在加入后使用
  • 匿名命名空間就類似于static
  • 命名空間可以取別名
  • 分文件編寫的時(shí)候,如果頭文件有兩個(gè)命名空間,但是里面的成員函數(shù)或者成員變量同名的時(shí)候,在cpp重實(shí)現(xiàn)函數(shù)需要加上命名空間

接下來給一個(gè)完整的代碼塊來展示命名空間的注意事項(xiàng)和使用:

#include<iostream> //引入頭文件
#include<string>//C++中的字符串
using namespace std; //標(biāo)準(zhǔn)命名空間
//A就是命名空間的名字
namespace A
{	
	//命名空間內(nèi)既可以定義變量也可以定義函數(shù)
	int rand = 10;
	int Sub(int x, int y)
	{
		return x + y;
	}
	struct ListNode
	{
		int data;
		struct ListNode* next;
	};
}
//命名空間的嵌套定義
namespace B
{
	int rand;
	namespace C
	{
		int rand;
	}
}
//命名空間是開放的,隨時(shí)可以加入新成員,但是新成員只能在加入后使用
namespace B
{
	int c;//此時(shí)c會(huì)合并到命名空間B中,實(shí)際上就是個(gè)合并的過程
}
//匿名命名空間
namespace 
{
	int d = 5;//命名空間沒有名字,就類似于static int d = 50,是個(gè)靜態(tài)全局變量,別的文件無法使用
}
int main()
{
	//命名空間的使用
	//1.::作用域限定符
	//訪問A空間的Sub函數(shù)
	cout << A::Sub(10, 20) << endl;
	//2.訪問嵌套空間
	//訪問B空間的C空間的rand變量
	B::C::rand = 5;
	cout << B::C::rand << endl;

	system("pause");
	return EXIT_SUCCESS;
}

using關(guān)鍵字

引入using關(guān)鍵字之后,命名空間的使用又變得不一樣

  • 用using將命名空間的成員引入
namespace A
{
	int a = 10;
}
void test01()
{
	//using聲明的意思就是讓命名空間中某個(gè)標(biāo)識(shí)符可以直接使用
	using A::a;
	cout<<a<<endl;
}

注意:

1.使用using聲明,就不會(huì)每次寫A::a了,直接用a就可以

2.using A::a聲明的意思就是把變量a又在test函數(shù)中定義了一次,此時(shí)如果在test內(nèi)部再定義一個(gè)int a;就會(huì)出錯(cuò)

  • 用using namespace 命名空間名稱引入
namespace A
{
	int a = 10;
}
using namespace A;
void test01()
{
	cout<<a<<endl;
}

使用using關(guān)鍵字修飾namespace整個(gè)命名空間,實(shí)際上就是脫去了這個(gè)命名空間的外衣,就等價(jià)于你定義了一個(gè)int a在全局

思考一個(gè)問題:下面代碼有錯(cuò)嗎?

在test01函數(shù)體內(nèi)又定義了一個(gè)int a,會(huì)報(bào)錯(cuò)么?如果不報(bào)錯(cuò),那么輸出的是全局的 a = 10 還是局部的a = 20?

namespace A
{
	int a = 10;
}
using namespace A;
void test01()
{
	int a = 20;
	cout<<a<<endl;
}

答案是不會(huì)報(bào)錯(cuò),輸出的是局部的20,因?yàn)槊臻gA內(nèi)部的變量a在使用using關(guān)鍵字后相當(dāng)于在全局定義了一個(gè)int a ;而在函數(shù)體內(nèi)定義一個(gè)局部的 int a;兩個(gè)變量的作用域不同,是可以定義同名變量的,輸出的是局部變量的值,小伙伴的要注意區(qū)分~

C++輸入和輸出

  • C語言用的是printf和scanf進(jìn)行輸入和輸出的。那么C++是用什么來進(jìn)行輸入輸出的呢?
  • C++用到的是cout(控制臺(tái))和cin(鍵盤)兩個(gè)函數(shù)進(jìn)行操作,使用是必須包含iostream的頭文件及 std標(biāo)準(zhǔn)命名空間。
  • C++頭文件不帶.h,將std標(biāo)準(zhǔn)命名空間進(jìn)行展開。
#include <iostream>
using namespace std;// 將std標(biāo)準(zhǔn)命名空間進(jìn)行展開

int main()
{
	cout << "hello world" << endl;
	// std::cout << "hello world" << endl; 也可以這樣寫就不展開std標(biāo)準(zhǔn)命名空間
	return 0;
}

使用C++輸入輸出更方便,不需增加數(shù)據(jù)格式控制,比如:整形–%d,字符–%c

int main()
{
	int a = 0;
	double b = 0.0;

	cin >> a;
	cin >> b;

	cout << "a = " << a << " b = " << b << endl;
	system("pause");
	return EXIT_SUCCESS;
}

運(yùn)行結(jié)果如下:

缺省參數(shù)

概念:

缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)默認(rèn)值。在調(diào)用該函數(shù)時(shí),如果沒有指定實(shí)參則采用該默認(rèn)值,否則使用指定的實(shí)參。

void PrintNum(int n = 0)
{
	cout &lt;&lt; n &lt;&lt; endl;
}

int main()
{
	PrintNum();// 無參數(shù)時(shí),使用參數(shù)的默認(rèn)值
	PrintNum(10);// 有參數(shù)時(shí),使用指定的實(shí)參
	system("pause");
	return EXIT_SUCCESS;
}

全缺省參數(shù)

參數(shù)都要一個(gè)默認(rèn)值,給定的實(shí)參依次從左向右給形參賦值

注意:我們?cè)谡{(diào)用函數(shù)時(shí),只能缺省最右邊的若干個(gè)參數(shù),形如:Fun(4, , 6);這種調(diào)用是錯(cuò)誤的調(diào)用方法。

void Func(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}


int main()
{
	// 實(shí)參從左向右一次給形參賦值
	Func();
	Func(1);
	Func(1, 2);
	Func(1, 2, 3);
	system("pause");
	return EXIT_SUCCESS;
}

運(yùn)行結(jié)果如下:

半缺省參數(shù)

只有部分形參給定了默認(rèn)值,半缺省參數(shù)必須從右往左依次來給出,不能間隔著給。

值得注意的是,缺省參數(shù)只能為最右邊的若干個(gè)

形如:void Fun(int a=10, int b, int c = 30) { }這樣的語句是錯(cuò)誤的用法。

形如:Fun(1, ,3)這種調(diào)用也是錯(cuò)誤的。

void Func(int a, int b = 10, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

int main()
{
	Func(1);
	Func(1, 2);
	Func(1, 2, 3);
	system("pause");
	return EXIT_SUCCESS;
}

運(yùn)行結(jié)果如下:

注意:

  • 半缺省參數(shù)必須從右向左依次給出,不能間隔著給
  • 缺省參數(shù)不能在聲明中和定義中同時(shí)出現(xiàn)(推薦寫在聲明中)
  • 缺省參數(shù)必須是全局變量和常量
  • C語言中不支持缺省參數(shù)

const限定符

const修飾符的作用

  • const類型定義: 指明變量或?qū)ο蟮闹凳遣荒鼙桓?引入目的是為了取代預(yù)編譯指令
  • 可以保護(hù)被修飾的東西,防止意外的修改,增強(qiáng)程序的健壯性
  • 編譯器通常不為普通const常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高
  • 可以節(jié)省空間,避免不必要的內(nèi)存分配

規(guī)則

  • const離誰近,誰就不能被修改
  • const修飾一個(gè)變量時(shí),一定要給這個(gè)變量初始化,若不初始化,在后面也不能初始化

分類

  常變量:  const 類型說明符 變量名

  常引用:  const 類型說明符 &引用名

  常對(duì)象:  類名 const 對(duì)象名

  常成員函數(shù):  類名::fun(形參) const

  常數(shù)組:  類型說明符 const 數(shù)組名[大小]    

  常指針:  const 類型說明符* 指針名 ,類型說明符* const 指針名

const全局/局部變量

C

在C語言中const修改全局變量是存儲(chǔ)在全局區(qū)(即靜態(tài)存儲(chǔ)區(qū)),修飾局部變量時(shí)存儲(chǔ)在棧區(qū)

//const修飾的常量
const int a = 10;//全局const常量,放在常量區(qū),受到常量區(qū)的保護(hù)
void test01()
{
	//直接修改失敗
	a = 100;
	//間接修改失敗
	int *p = &a;
	*p = 100;
}
  • 全局的const修飾的變量本質(zhì)就是常量,全局const修飾的變量放在常量區(qū)中,不能通過變量名直接修改也不可以通過地址來間接修改
//局部conts修飾常量
void test02()
{
	conts int b = 10;//數(shù)據(jù)放在棧區(qū),是個(gè)偽常量
	//直接修改失敗
	b = 100;
	//間接修改成功
	int *p = &b;
	*p = 100;
}
  • 局部const修飾的變量是個(gè)偽常量,不是真正意義上的常量,數(shù)據(jù)存放在棧區(qū)而不是常量區(qū),可以間接修改但是不能直接修改。

總結(jié):

  • C語言的const修飾的全局變量和局部變量都有空間
  • C語言的const修飾的全局變量具有外部鏈接屬性,可以采用extern聲明在別的文件中使用

C++

在C++中編譯器會(huì)自動(dòng)優(yōu)化,會(huì)將常量的數(shù)值直接替換(類似于宏定義),這導(dǎo)致了const局部變量與真實(shí)值產(chǎn)生了不一致。(常量折疊現(xiàn)象),而C語言會(huì)先去內(nèi)存中尋找,然后替換

舉個(gè)例子:

const int aa = 10;//沒有內(nèi)存
void test01()
{
	cout << aa << endl;//在編譯階段,編譯器會(huì)自動(dòng)優(yōu)化,將aa直接替換成常量10
	const int bb = 20;//棧區(qū)
	int *p = (int *)&bb;
	*p = 200;
	cout << bb << endl;//輸出的還是20,還是那句話,在編譯階段代碼中的bb就已經(jīng)全部被替換成20,此時(shí)其實(shí)輸出的是這樣的cout << 20 << endl;但是變量bb此時(shí)的值已經(jīng)被改變了,變成了200,但是由于編譯器優(yōu)化,造成了常量折疊現(xiàn)象
}

總結(jié):

  • C++語言的const修飾的變量有時(shí)有空間,有時(shí)沒有空間(發(fā)生常量折疊,且沒有對(duì)變量進(jìn)行取地址操作)
  • C++中,const修飾的全局變量具有內(nèi)部鏈接屬性,也就是說,無法使用別的文件的const修飾的變量,但是這種規(guī)則依舊可以打破
  • const修飾的全局變量永遠(yuǎn)都沒有內(nèi)存,永遠(yuǎn)無法修改它的值,但是const修飾的局部變量可以有空間,可以修改它的值

編譯器不能優(yōu)化的情況

  • 不能優(yōu)化自定義數(shù)據(jù)類型
  • 如果用變量給const修飾的局部變量賦值,那么編譯器也不能優(yōu)化
  • 使用extern和voaltile關(guān)鍵字來阻止優(yōu)化

例子一:用變量給const修飾的局部變量賦值

void test03()
{
	int a =10;
	const int b = a;
	int *p = (int *)&b;
	*p = 100;
	cout << b << endl;//輸出100
}

例子二:利用關(guān)鍵字阻止優(yōu)化

void test04()
{
	const volatile int a = 7;
	int *p = (int *)(&a);
	*p = 8;
	cout << "a=" << a << endl;//輸出8
	cout << "*p=" << *p;
	system("pause");
	return 0;
}

例子三:自定義數(shù)據(jù)類型不能優(yōu)化

struct Maker
{
	Maker()
	{
		a = 100;
	}
	int a;
};
void test05()
{
	const Maker ma;
	cout << ma.a <<endl;
	Maker *p = (Maker*)&ma;
	p->a = 200;//可以修改ma中的值
	cout << ma.a << endl;
}

const修飾指針和引用

const修飾指針

涉及到兩個(gè)很重要的概念,頂層const底層const

從 const 指針開始說起。const int* pInt; 和 int *const pInt = &someInt;,前者是 *pInt 不能改變,而后者是 pInt 不能改變。因此指針本身是不是常量和指針?biāo)赶虻膶?duì)象是不是常量就是兩個(gè)互相獨(dú)立的問題。用頂層表示指針本身是個(gè)常量,底層表示指針?biāo)赶虻膶?duì)象是個(gè)常量。更一般的,頂層 const 可以表示任意的對(duì)象是常量,這一點(diǎn)對(duì)任何數(shù)據(jù)類型都適用;底層 const 則與指針和引用等復(fù)合類型有關(guān),比較特殊的是,指針類型既可以是頂層 const 也可以是底層 const 或者二者兼?zhèn)洹?/p>

int a = 1;
int b = 2;
const int* p1 = &a;//指針常量(頂層const)
int* const p2 = &a;//常量指針(底層const)
1.指針常量(指針不可改,指針指向的對(duì)象可改)

int a = 10;
int b = 5;
int * const p1 = &a;
p1 = &b; //指針不可改,不合法
*p1 = b; //指針指向的對(duì)象可改,合法

2.常量指針(指針可改,指針指向的對(duì)象不可改)
int a = 10;
int b = 5;
const int* p2 = &a;
p2 = &b; //指針可改, 合法
*p2 = b; //不合法

拷貝與頂層和底層 const

int i = 0;
int *const p1 = &i;     //  不能改變 p1 的值,這是一個(gè)頂層
const int ci = 42;      //  不能改變 ci 的值,這是一個(gè)頂層
const int *p2 = &ci;    //  允許改變 p2 的值,這是一個(gè)底層
const int *const p3 = p2;   //  靠右的 const 是頂層 const,靠左的是底層 const
const int &r = ci;      //  所有的引用本身都是頂層 const,因?yàn)橐靡坏┏跏蓟筒荒茉俑臑槠渌麑?duì)象的引用,這里用于聲明引用的 const 都是底層 const

const修飾引用

常引用所引用的對(duì)象不能更新,使用方法為:const 類型說明符 &引用名

非const引用只能綁定非const對(duì)象,const引用可以綁定任意對(duì)象,并且都當(dāng)做常對(duì)象

常引用經(jīng)常用作形參,防止函數(shù)內(nèi)對(duì)象被意外修改。對(duì)于在函數(shù)中不會(huì)修改其值的參數(shù),最好都聲明為常引用。復(fù)制構(gòu)造函數(shù)的參數(shù)一般均為常引用

class Example{
public:
    Example(int x, int y):a(x),b(y){}
    Example(const Example &e):a(e.a),b(e.b){} //復(fù)制構(gòu)造函數(shù)
    void print();
    void print() const;
private:
    const int a,b;
    static const int c = 10;
};
void Example::print() {cout<<"print():"<<a<<ends<<b<<endl;}
void Example::print() const {cout<<"print() const:"<<a<<ends<<b<<endl;}

const修飾函數(shù)參數(shù)

const修飾參數(shù)是為了防止函數(shù)體內(nèi)可能會(huì)修改參數(shù)原始對(duì)象。因此,有三種情況可討論:

  • 1、函數(shù)參數(shù)為值傳遞:值傳遞(pass-by-value)是傳遞一份參數(shù)的拷貝給函數(shù),因此不論函數(shù)體代碼如何運(yùn)行,也只會(huì)修改拷貝而無法修改原始對(duì)象,這種情況不需要將參數(shù)聲明為const。
  • 2、函數(shù)參數(shù)為指針:指針傳遞(pass-by-pointer)只會(huì)進(jìn)行淺拷貝,拷貝一份指針給函數(shù),而不會(huì)拷貝一份原始對(duì)象。因此,給指針參數(shù)加上頂層const可以防止指針指向被篡改,加上底層const可以防止指向?qū)ο蟊淮鄹摹?/li>
  • 3、函數(shù)參數(shù)為引用:引用傳遞(pass-by-reference)有一個(gè)很重要的作用,由于引用就是對(duì)象的一個(gè)別名,因此不需要拷貝對(duì)象,減小了開銷。這同時(shí)也導(dǎo)致可以通過修改引用直接修改原始對(duì)象(畢竟引用和原始對(duì)象其實(shí)是同一個(gè)東西),因此,大多數(shù)時(shí)候,推薦函數(shù)參數(shù)設(shè)置為pass-by-reference-to-const。給引用加上底層const,既可以減小拷貝開銷,又可以防止修改底層所引用的對(duì)象。
void Fun(const A *in); //修飾指針型傳入?yún)?shù)
void Fun(const A &in); //修飾引用型傳入?yún)?shù)

void func (const int& n)
{
     n = 10;        // 編譯錯(cuò)誤 
}

const修飾函數(shù)返回值

const修飾函數(shù)返回值的含義和用const修飾普通變量以及指針的含義基本相同。這樣可以防止外部對(duì) object 的內(nèi)部成員進(jìn)行修改。

const int* func()   // 返回的指針?biāo)赶虻膬?nèi)容不能修改
{
    // return p;
}

const成員函數(shù)和數(shù)據(jù)成員

類的常成員函數(shù)

由于C++會(huì)保護(hù)const對(duì)象不被更新,為了防止類的對(duì)象出現(xiàn)意外更新,禁止const對(duì)象調(diào)用類的非常成員函數(shù)。因此,常成員函數(shù)為常對(duì)象的唯一對(duì)外接口。

常成員函數(shù)的聲明方式:類型說明符 函數(shù)名(參數(shù)表) const

  • const對(duì)象只能訪問const成員函數(shù),而非const對(duì)象可以訪問任意的成員函數(shù),包括const成員函數(shù)
  • const對(duì)象的成員是不能修改的,而通過指針維護(hù)的對(duì)象卻是可以修改的
  • const成員函數(shù)不可以修改對(duì)象的數(shù)據(jù),不管對(duì)象是否具有const性質(zhì)。編譯時(shí)以是否修改成員數(shù)據(jù)為依據(jù)進(jìn)行檢查
class A
{
public:
	//返回值的類型是int &類型
    int& getValue() const
    {
        // a = 10;    // 錯(cuò)誤
        return a;
    }

private:
    int a;            // 非const成員變量
};

注意事項(xiàng):

  • 常成員函數(shù)的定義和聲明都要含有const關(guān)鍵字
  • 一個(gè)函數(shù)是否含有const關(guān)鍵字可以作為重載函數(shù),const對(duì)象默認(rèn)調(diào)用const函數(shù),非const對(duì)象默認(rèn)調(diào)用非const函數(shù),如果沒有非const函數(shù),也可以調(diào)用const函數(shù)
  • const函數(shù)中不能更新目的對(duì)象的任何成員(mutable修飾的變量除外,這里不展開闡述),以此方法來保證const對(duì)象不被修改
  • 如果const成員函數(shù)想修改成員變量值,可以用mutable修飾目標(biāo)成員變量

類的常數(shù)據(jù)成員

類的數(shù)據(jù)成員不能在任何函數(shù)中被賦值或修改,但必須在構(gòu)造函數(shù)中使用初始化列表的方式賦初值,因?yàn)閏onst修飾的對(duì)象必須初始化。
舉個(gè)例子,剛才的類如果a, b為常數(shù)據(jù)成員,則應(yīng)該改寫為如下形式:

class Example{
public:
    Example(int x, int y):a(x),b(y){} //初始化列表方式賦初值
    void print();
    void print() const;
private:
    const int a,b;
};
void Example::print() {cout<<"print():"<<a<<ends<<b<<endl;}
void Example::print() const {cout<<"print() const:"<<a<<ends<<b<<endl;}

如果為靜態(tài)常數(shù)據(jù)成員,由于不屬于具體對(duì)象,所以不能在構(gòu)造函數(shù)里賦值,仍然應(yīng)該在類外賦值。特別地,如果靜態(tài)常量為整數(shù)或枚舉類型,C++允許在類內(nèi)定義時(shí)指定常量值。
比如以下兩種方式均合法:

class Example{
public:
    Example(int x, int y):a(x),b(y){}
    void print();
    void print() const;
private:
    const int a,b;
    static const int c = 10; //靜態(tài)常量
};
class Example{
public:
    Example(int x, int y):a(x),b(y){}
    void print();
    void print() const;
private:
    const int a,b;
    static const int c; //靜態(tài)常量
};
const int Example::c = 10;

const修飾類對(duì)象

用const修飾的類對(duì)象,該對(duì)象內(nèi)的任何成員變量都不能被修改。
因此不能調(diào)用該對(duì)象的任何非const成員函數(shù),因?yàn)閷?duì)非const成員函數(shù)的調(diào)用會(huì)有修改成員變量的企圖。

class A
{
 public:
    void funcA() {}
    void funcB() const {}
};
int main
{
    const A a;
    a.funcB();    // 可以
    a.funcA();    // 錯(cuò)誤

    const A* b = new A();
    b->funcB();    // 可以
    b->funcA();    // 錯(cuò)誤
}

const與宏定義的區(qū)別

(1) 編譯器處理方式不同
  define宏是在預(yù)處理階段展開。
  const常量是編譯運(yùn)行階段使用。

(2) 類型和安全檢查不同
  define宏沒有類型,不做任何類型檢查,僅僅是展開。
  const常量有具體的類型,在編譯階段會(huì)執(zhí)行類型檢查。

(3) 存儲(chǔ)方式不同
  define宏僅僅是展開,有多少地方使用,就展開多少次,不會(huì)分配內(nèi)存。
  const常量會(huì)在內(nèi)存中分配(可以是堆中也可以是棧中)。

(4)作用范圍不同

? const有作用域,而define不重視作用域,默認(rèn)定義處到文件結(jié)束,如果定義在指定作用域下有效的常量,那么define不能用。

(5)const 可以節(jié)省空間,避免不必要的內(nèi)存分配。 例如:

  #define PI 3.14159 //常量宏  
    const doulbe Pi=3.14159; //此時(shí)并未將Pi放入ROM中 ......  
    double i=Pi; //此時(shí)為Pi分配內(nèi)存,以后不再分配!  
    double I=PI; //編譯期間進(jìn)行宏替換,分配內(nèi)存  
    double j=Pi; //沒有內(nèi)存分配  
    double J=PI; //再進(jìn)行宏替換,又一次分配內(nèi)存!  

const定義常量從匯編的角度來看,只是給出了對(duì)應(yīng)的內(nèi)存地址,而不是像#define一樣給出的是立即數(shù),所以,const定義的常量在程序運(yùn)行過程中只有一份拷貝,而 #define定義的常量在內(nèi)存中有若干個(gè)拷貝。

const與static的區(qū)別

static

1、static局部變量 將一個(gè)變量聲明為函數(shù)的局部變量,那么這個(gè)局部變量在函數(shù)執(zhí)行完成之后不會(huì)被釋放,而是繼續(xù)保留在內(nèi)存中

2、static 全局變量 表示一個(gè)變量在當(dāng)前文件的全局內(nèi)可訪問

3、static 函數(shù) 表示一個(gè)函數(shù)只能在當(dāng)前文件中被訪問

4、static 類成員變量 表示這個(gè)成員為全類所共有

5、static 類成員函數(shù) 表示這個(gè)函數(shù)為全類所共有,而且只能訪問靜態(tài)成員變量

static關(guān)鍵字的作用

(1)函數(shù)體內(nèi)static變量的作用范圍為該函數(shù)體,該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時(shí)仍維持上次的值
(2)在模塊內(nèi)的static全局變量和函數(shù)可以被模塊內(nèi)的函數(shù)訪問,但不能被模塊外其它函數(shù)訪問
(3)在類中的static成員變量屬于整個(gè)類所擁有,對(duì)類的所有對(duì)象只有一份拷貝
(4)在類中的static成員函數(shù)屬于整個(gè)類所擁有,這個(gè)函數(shù)不接收this指針,因而只能訪問類的static成員變量

const關(guān)鍵字的作用

(1)阻止一個(gè)變量被改變
(2)聲明常量指針和指針常量
(3)const修飾形參,表明它是一個(gè)輸入?yún)?shù),在函數(shù)內(nèi)部不能改變其值
(4)對(duì)于類的成員函數(shù),若指定其為const類型,則表明其是一個(gè)常函數(shù),不能修改類的成員變量
(5)對(duì)于類的成員函數(shù),有時(shí)候必須指定其返回值為const類型,以使得其返回值不為”左值”

引用

概念

引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會(huì)為引用變量開辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。也就好比我們給同學(xué)取了一個(gè)外號(hào)一樣。
用法: 類型&引用變量名(對(duì)象名)= 引用實(shí)體;

int main()
{
	int a = 10;
	int& ra = a;// ra是a的引用

	cout << a << endl;
	cout << ra << endl;

	system("pause");
	return EXIT_SUCESS;
}

特性及注意事項(xiàng)

  • 引用在定義的時(shí)候必須初始化
  • 一個(gè)變量可有多個(gè)引用
  • 引用一個(gè)引用一個(gè)實(shí)體,無法再引用其他實(shí)體

Type& ref = val;

注意事項(xiàng):

  • &在此不是取地址運(yùn)算符,而是起到一個(gè)標(biāo)識(shí)的作用
  • 類型標(biāo)識(shí)符指的是目標(biāo)變量的類型
  • 引用初始化之后不能改變
  • 不能有NULL引用,必須確保引用是和一塊合法的存儲(chǔ)單元關(guān)聯(lián)
int a = 10;
int b = 20;

//int& ra;//引用必須初始化

int& ra = a;
int& rra = a;

//int& ra = b;//引用一旦初始化,不能改變它的指向
//int& raaa = NULL;//NULL本身就是不合法的,不能綁定不合法的空間

數(shù)組的引用

int arr[] = {1, 2, 3, 4, 5};
//三種方式
//1.定義數(shù)組類型
typedef int(MY_ARR)[5];
MY_ARR &arref = arr;//建立引用,int &b = a

//2.直接定義引用
int(&arref2)[5] = arr;

//3.建立引用數(shù)組類型
typedef int(&MY_ARR3)[5];
MY_ARR3 arref3 = arr;

引用的使用場(chǎng)景

//1.作為函數(shù)的參數(shù)
void func(int &a, int &b)
{
	cout << a+b << endl;
}
//2.引用作為函數(shù)的返回值
int& func2()
{
	int b = 10;//不能返回局部變量的引用
	int &p = b;
	return p;//錯(cuò)誤的
}
int& func3()
{
	static int b = 10;
	return b;
}
void test01()
{
	int& q = func2();
	cout << q << endl;
	q = 100;
	cout << q << endl;

	func2() = 200;
	cout << q << endl;
	cout << func2() << endl;
//--------------上面的代碼都是錯(cuò)誤的,這里解釋一下
//int& q = func2();實(shí)際上就是int&q = p,但是fun2函數(shù)執(zhí)行完了之后,局部變量全部被銷毀了,所以int&q = 就指向了一個(gè)非法的區(qū)域,但是編譯器沒有檢測(cè)出來,具體原因是什么不清楚
	func3() = 100;
	cout << func3() << endl;
}

引用做返回值時(shí),一般分兩種情況:返回的對(duì)象未歸還系統(tǒng)和返回的對(duì)象歸還系統(tǒng)。如果返回對(duì)象不歸還系統(tǒng),我們可以引用返回,否則就需要傳值返回

想要返回局部變量:1.把局部變量寫在堆區(qū) 2.把局部變量寫在靜態(tài)區(qū)

常引用

注意:

  • 字面不能賦給引用,但是可以賦給const引用
  • const修飾的引用,不能修改
//普通引用
int a = 10;
int &ref = a;
ref = 20;
//int &ref2 = 10不能給字面量取別名,因?yàn)?0這個(gè)字面量在內(nèi)存中沒有空間,存儲(chǔ)在寄存器中

//常引用
const int &ref3 = 10;//可以給const修飾的引用賦予字面量
//編譯器會(huì)把上面的代碼變?yōu)椋篿nt tmp = 10;const int &ref3 = tmp;

內(nèi)聯(lián)函數(shù)

inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會(huì)在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,沒有函數(shù)壓棧的開銷,內(nèi)聯(lián)函數(shù)提升程序運(yùn)行的效率。

inline int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int z = Add(1, 2);
	return 0;
}

如果加了inline關(guān)鍵字,編譯器在編譯期間會(huì)用函數(shù)體替換函數(shù)的調(diào)用(類似于宏定義,在編譯階段就替換函數(shù)調(diào)用,將函數(shù)調(diào)用直接展開,減少了調(diào)用的時(shí)間,但是空間消耗巨大)。

下面是內(nèi)斂函數(shù)的幾個(gè)特性:

1.inline是一種以空間換時(shí)間的做法,省去調(diào)用函數(shù)額開銷。所以代碼很長或者有循環(huán)/遞歸的函數(shù)不適宜使用作為內(nèi)聯(lián)函數(shù)。
2.inline對(duì)于編譯器而言只是一個(gè)建議,編譯器會(huì)自動(dòng)優(yōu)化,如果定義為inline的函數(shù)體內(nèi)有循環(huán)/遞歸等等,編譯器優(yōu)化時(shí)會(huì)忽略掉內(nèi)聯(lián)(是否稱為內(nèi)聯(lián)函數(shù)由編譯器決定)。
3.inline不建議聲明和定義分離,分離會(huì)導(dǎo)致鏈接錯(cuò)誤。因?yàn)閕nline被展開,就沒有函數(shù)地址了,鏈接就會(huì)找不到。

例子:一個(gè)相同的函數(shù),一個(gè)加了inline 關(guān)鍵字,一個(gè)沒加,加上一個(gè)函數(shù)要執(zhí)行10條指令,文兩個(gè)函數(shù)分別調(diào)用1000次要執(zhí)行多少條指令?
普通函數(shù):1000+10(一次調(diào)用1次指令,加起來就是1000條,每次調(diào)用都是call函數(shù),函數(shù)不展開就是10條)
內(nèi)聯(lián)函數(shù):1000*10條指令(展開就是每次調(diào)用都是10條指令)
所以說,內(nèi)聯(lián)函數(shù)展開,會(huì)讓程序變大,所以代碼很短的函數(shù)可以考慮有內(nèi)聯(lián),長函數(shù)和遞歸函數(shù)不適合用內(nèi)聯(lián)。

auto關(guān)鍵字

C++11中,標(biāo)準(zhǔn)委員會(huì)賦予了auto全新的含義即:auto不再是一個(gè)存儲(chǔ)類型指示符,而是作為一個(gè)新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時(shí)期推導(dǎo)而得。

int a = 10;
auto b = a;// 自動(dòng)推導(dǎo)b的類型為int
auto c = 'c';// 自動(dòng)推導(dǎo)類型為char

cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
//auto d;必須初始化

有一下幾種用法:

  • auto與指針和引用結(jié)合起來使用(auto和auto*無區(qū)別)
int a = 10;
// auto和auto*無區(qū)別
auto pa1 = &a;
auto* pa2 = &a;

auto& ra = a;// ==> int& ra = a;

cout << typeid(a).name() << endl;
cout << typeid(pa1).name() << endl;
cout << typeid(pa2).name() << endl;
cout << typeid(ra).name() << endl;

運(yùn)行結(jié)果如下:

  • 在同一行定義多個(gè)變量(這些變量類型必須相同,編譯器只對(duì)第一個(gè)類型進(jìn)行推導(dǎo))
auto a = 3, b = 4;
auto c = 3.4, d = 5.5;
auto i =0, *p = &i;//正確,i是整型,p是整型指針

cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(i).name() << endl;
cout << typeid(p).name() << endl;

auto不能推導(dǎo)的兩個(gè)常見

  • auto不能作為函數(shù)的參數(shù)
  • auto不能直接用來聲明數(shù)組

到此這篇關(guān)于C++命名空間 缺省參數(shù) const總結(jié) 引用總結(jié) 內(nèi)聯(lián)函數(shù) auto關(guān)鍵字詳解的文章就介紹到這了,更多相關(guān)C++入門內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實(shí)現(xiàn)哈夫曼編碼

    C語言實(shí)現(xiàn)哈夫曼編碼

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)哈夫曼編碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++使用TinyXml實(shí)現(xiàn)讀取XMl文件

    C++使用TinyXml實(shí)現(xiàn)讀取XMl文件

    常見C/C++?XML解析器有Tinyxml、XERCES、squashxml、xmlite、pugxml、libxml等等,本文為大家介紹的是使用TinyXml實(shí)現(xiàn)讀取XMl文件,需要的可以參考一下
    2023-06-06
  • 利用C語言實(shí)現(xiàn)五子棋游戲

    利用C語言實(shí)現(xiàn)五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了利用C語言實(shí)現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++ Boost Exception超詳細(xì)講解

    C++ Boost Exception超詳細(xì)講解

    Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個(gè)可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱
    2022-11-11
  • C/C++實(shí)現(xiàn)HTTP協(xié)議解析的示例代碼

    C/C++實(shí)現(xiàn)HTTP協(xié)議解析的示例代碼

    基本上,HTTP?是一種基于?TCP/IP?的通信協(xié)議,用于通過?Web?傳遞?HTML?文件、圖像文件、查詢結(jié)果等數(shù)據(jù)。本文將用C/C++實(shí)現(xiàn)HTTP協(xié)議解析,感興趣的可以了解一下
    2022-07-07
  • C++特殊成員函數(shù)以及其生成機(jī)制詳解

    C++特殊成員函數(shù)以及其生成機(jī)制詳解

    這篇文章主要給大家介紹了關(guān)于C++特殊成員函數(shù)以及其生成機(jī)制的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • 基于VS2019配置opencv4.0的方法步驟

    基于VS2019配置opencv4.0的方法步驟

    這篇文章主要介紹了基于VS2019配置opencv4.0的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 詳細(xì)聊一聊algorithm中的排序算法

    詳細(xì)聊一聊algorithm中的排序算法

    <algorithm>是C++標(biāo)準(zhǔn)程序庫中的一個(gè)頭文件,定義了C++?STL標(biāo)準(zhǔn)中的基礎(chǔ)性的算法(均為函數(shù)模板),下面這篇文章主要給大家介紹了關(guān)于algorithm中排序算法的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • c++ 臨時(shí)對(duì)象的來源

    c++ 臨時(shí)對(duì)象的來源

    大家可能對(duì)這個(gè)臨時(shí)對(duì)象這個(gè)概念還不是很清楚,那么首先我們花一些時(shí)間來理解臨時(shí)對(duì)象
    2013-01-01
  • C++字符串的截取問題

    C++字符串的截取問題

    這篇文章主要介紹了C++字符串的截取問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論