1. 程式人生 > >C++:名稱空間、預設引數、函式過載、引用、行內函數

C++:名稱空間、預設引數、函式過載、引用、行內函數

一.名稱空間

          在C/C++中,變數、函式和類都是大量存在的,這些變數、函式和類的名稱都將作用於全域性作用域中,可能會導致很多衝突,所以我們就選擇使用名稱空間。

          名稱空間的目的是對識別符號的名稱進行本地化,以避免命名衝突或者名字汙染。

    1.定義:

     定義一個名稱空間,需要用到namespace關鍵字,後跟名稱空間。

namespace n1//普通的名稱空間
{
	int a = 10;//定義變數
	int b = 20;
	int add(int left, int right)//定義函式
	{
		return left + right;
	}
}
namespace n2
{
	int c = 30;
	int sub(int left, int right)
	{
		return left - right;
	}
	namespace n3//名稱空間可以巢狀
	{
		int mul(int left, int right)
		{
			return left*right;
		}
	}
}
namespace n1//同一個工程中允許多個相同名稱的名稱空間,編譯器會將多個合成一個名稱空間
{
	int c = 50;
}

    2.使用(三種方式) 

          (1)使用作用域限定符

int main()
{
	printf("%d\n",n1::a );
	system("pause");
	return 0;
}

            

          (2)使用using將名稱空間中的成員引入

using n1::b;
int main()
{
	printf("%d\n", b);
	system("pause");
	return 0;
}

          (3)使用using namespace名稱空間名稱引入

using namespace n1;
int main()
{
	printf("%d\n", add(10, 20));
	system("pause");
	return 0;
}

二.預設引數

          1.概念

               預設引數是宣告或者定義函式時對函式的引數指定一個預設值。在呼叫函式時,如果沒有指定實參則採用預設值,否則使用指定的實參。

void test(int a = 100)
{
	cout << a << endl;
}
int main()
{
	test();//無參
	test(10);//有參
	system("pause");
	return 0;
}

         2.分類

          (1)全預設引數

          (2)半預設引數

void test(int a = 100, int b = 10, int c = 1)//全預設引數
{
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
	cout << "c=" << c << endl;
}
void test(int a, int b = 10, int c = 1)//半預設引數
{
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
	cout << "c=" << c << endl;
}

         3.特點

              (1)半預設引數必須從右到左依次給出,不能間隔。

              (2)預設引數不能同時在函式宣告和定義中出現。

              (3)預設值必須是常量或者全域性變數

              (4)C語言不支援

三.函式過載

     1.函式過載是函式的一種特殊情況,C++允許在同一個作用域中宣告幾個功能類似的同名函式,這些同名函式的形參必須不同。常用於處理功能類似但是型別不同的問題。

 

int add(int a, int b)
{
	return a + b;
}
double add(double a, double b)
{
	return a + b;
}
long add(long a, long b)
{
	return a + b;
}
short add(short a, short b)
{
	return a + b;
}

int main()
{
	int ret1 = add(1, 2);
	double ret2 = add(1.0, 2.0);
	long ret3 = add(1L, 2L);
	short ret4 = add(1, 2);
	system("pause");
	return 0;
}

 

extern"C"在C++工程中將某個函式按照C的風格來編譯。

四.引用

      1.概念

            引用不是定義一個變數,而是給已存在的變數去一個別名, 編譯器不會為引用變數開闢記憶體空間,它和它的引用空間公用一塊記憶體空間

void test()//引用型別必須和引用實體是同類型的
{
	int a = 10;
	int & ra = a;
	printf("%p\n", &a);
	
}

      2.  特性

           (1)引用在定義時必須初始化

           (2)一個變數可以有多個引用

           (3) 引用一旦引用了一個實體,再不能引用其他實體

void test1()//引用型別必須和引用實體是同類型的
{
	int a = 10;
	//int &ra;//這條語句會出錯
	int & ra = a;
	int& rra = a;
	printf("%p\n", &a);
	printf("%p\n", &ra);
	printf("%p\n", &rra);
}

      3. 常引用

void test()
{
	const int a = 10;
	//int & ra = a;      //出錯
	const int& rra = a;
	double b = 20.0;
	//int& rb = b;         //出錯
	const double&rrb = b;
}

     4.使用場景

           (1)作引數

void swap(int& x, int& y)
{
	int tmp = x;
	x = y;
	y = tmp;
}

           (2)作返回值

int& testret(int&a)
{
	a = a + 10;
	return a;
}

      5.傳值、傳地址、傳引用效率比較

struct A
{
	int arr[10000];
	int size;
};
void testref(A& param)
{

}
void test()
{
	A a;
	size_t begin = GetTickCount();//從開機到現在的時間
	for (size_t i = 0; i < 1000000; i++)
		testref(a);//傳指標  16     傳引用  15
	size_t end = GetTickCount();
	cout << end - begin << endl;
}

通過比較,我們發現引用和指標在傳參的效果幾乎相同 

      6.引用和指標的區別

           (1)引用自在定義時必須初始化,指標沒有要求;

           (2)引用在初始化時引用一個實體後,就不能在引用其他實體,而指標可以在任何時候指向一個同類型實體;

           (3)沒有NULL引用,有NULL指標;

           (4)在sizeof中含義不同,引用的結果為引用型別的大小;指標永遠就是地址所佔的位元組數;

           (5)引用自加一即是引用實體增加一,指標自加一即是指標向後偏移一個型別的大小;

           (6)有多級指標,但是沒有多級引用;

           (7)訪問實體型別不同;指標需要顯示解引用,引用編譯器自己處理

           (8)引用比指標使用起來相對更安全

五.行內函數

        1.概念

              以inline修飾的函式叫作行內函數,編譯時C++編譯器會在呼叫行內函數的地方展開,沒有函式壓棧的開銷,行內函數提升程式執行效率。

int add(int x, int y)
{
	return x + y;
}
int main()
{
	int ret = 0;
	ret = add(10, 20);
	cout << ret << endl;
	system("pause");
	return 0;
}

                 在release下,彙編程式碼中沒有call;

                在debug下,先對編譯器修改;如下:專案-->xxx.cpp屬性-->配置(Debug)

     沒有call指令

 

        2.特性

               (1)inline是一種以空間換取時間的做法,省去呼叫函式的開銷,所以程式碼很長或者有迴圈/遞迴的函式不適合使用行內函數。

               (2)inline對於編譯器而言只是一個建議,編譯器會自動優化,如果定義為inline的函式中有迴圈/遞迴等等,編譯器會在優化時忽略掉行內函數。