最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中函數(shù)重載與引用的操作方法

 更新時(shí)間:2024年10月24日 10:51:59   作者:Yui_  
C++中函數(shù)重載允許同名函數(shù)根據(jù)參數(shù)列表的不同而執(zhí)行不同的功能,這依賴于名字修飾或名字改編(Name Mangling)機(jī)制,而引用則是為變量創(chuàng)建一個(gè)別名,不會(huì)開辟新的內(nèi)存空間,本文介紹了C++中函數(shù)重載與引用的操作,感興趣的朋友一起看看吧

1. 函數(shù)重載

在中文語(yǔ)境中有些詞語(yǔ)它就是一詞多義的,人們通過上下文來判斷詞語(yǔ)的意思,即該詞被重載了。
就比如說:以前有個(gè)笑話,我們國(guó)家有兩個(gè)體育項(xiàng)目大家根本不用看,也不用擔(dān)心。一個(gè)是乒乓球,一個(gè)是足球。前者"誰也贏不了"后者"誰也贏不了"。

1.1 函數(shù)重載概念

函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個(gè)功能類似的同名函數(shù),這些函數(shù)的形參列表(參數(shù)個(gè)數(shù)或者類型或者類型順序)不同,常用來處理功能類似數(shù)據(jù)類型不同的問題。

#include <iostream>
using namespace std;
//1.參數(shù)類型不同
int add(int left,int right)
{
	cout<<"int add(int left,int right)"<<endl;
	return left+right;
}
double add(double left,double right)
{
	cout<<"double add(double left,double right)"<<endl;
	return left+right;
}
//2.參數(shù)個(gè)數(shù)不同
void test()
{
	cout<<"test()"<<endl;
}
void test(int a)
{
	cout<<"test(int a)"<<endl;
}
//3.參數(shù)類型順序不同
void test2(int a,char b)
{
	cout<<"test2(int a,char b)"<<endl;
}
void test2(char b,int a)
{
	cout<<"test2(char b,int a)"<<endl;
}
int main()
{
	add(1,2);
	add(1.1,2.2);
	test();
	test(100);
	test2(10,'a');
	test2('a',10);
	return 0;
}

1.2 C++支持函數(shù)重載的原理–名字修飾(name Mangling)

為什么C++支持函數(shù)重載,而C語(yǔ)言不支持函數(shù)重載呢?
在C/C++中,一個(gè)程序要運(yùn)行起來,需要經(jīng)歷以下幾個(gè)階段:預(yù)處理、編譯、匯編、鏈接。

  • 實(shí)際項(xiàng)目中通常是由多個(gè)頭文件和多個(gè)源文件構(gòu)成的,而通過C語(yǔ)言階段學(xué)習(xí)的編譯鏈接,我們可以知道,【當(dāng)前a.cpp中調(diào)用了b.cpp中定義的Add函數(shù)時(shí)】,編譯后鏈接前,a.o的目標(biāo)文件中沒有Add的函數(shù)地址,因?yàn)锳dd是在b.cpp中定義的,所以Add的地址在b.o中。那么怎么辦呢?
  • 所以鏈接階段就是專門處理這種問題的,鏈接器看到a.o調(diào)用Add,但是沒有Add的地址,就會(huì)到b.o的符號(hào)表中找Add的地址,然后鏈接到一起。
  • 那么鏈接時(shí),面對(duì)Add函數(shù),鏈接器會(huì)使用哪個(gè)名字去找呢?這里每個(gè)編譯器都有自己的函數(shù)名修飾規(guī)則。
  • 由于windows下vs的修飾規(guī)則過于復(fù)雜,而Linux下g++的修飾規(guī)則簡(jiǎn)單易懂,下面我們使用了g++演示這個(gè)修飾后的名字。
  • 通過下面我們可以看到gcc的函數(shù)修飾后名字不變。而g++的函數(shù)修飾后變成【__Z+函數(shù)長(zhǎng)度+函數(shù)名+類型首字母】
  • 采用C語(yǔ)言編譯器編譯后的結(jié)果:
//file.c中的代碼
#include <stdio.h>
int Add(int a,int b)
{
    return a+b;
}
void test(int a,double b,int*p)
{
   //... 
}
int main()
{
    Add(10,20);
    test(1,2,0);
    return 0;
}

結(jié)論:在Linux下,采用gcc編譯完成后,函數(shù)名字的修飾沒有發(fā)生改變。

采用C++編譯器編譯后結(jié)果:

結(jié)論:在Linux下,采用g++編譯完成后,函數(shù)名字的修飾發(fā)生改變,編譯器將函數(shù)參數(shù)類型信息添加到修改后的名字中。

windows下名字修飾規(guī)則

總結(jié):對(duì)比Linux會(huì)發(fā)現(xiàn),Windows下vs編譯器對(duì)函數(shù)名字修飾規(guī)則相對(duì)復(fù)雜難懂,但道理類似。
6. 通過這里就理解了C語(yǔ)言沒辦法支持重載,因?yàn)橥瘮?shù)沒辦法區(qū)分。而C++是通過函數(shù)修飾規(guī)則來區(qū)分地,只要參數(shù)不同,修飾出來地名字就不一樣,那么就可以支持重載了。
7. 如果兩個(gè)函數(shù)函數(shù)名和參數(shù)是一樣的,返回值不同是不構(gòu)成重載的,因?yàn)檎{(diào)用時(shí)編譯器沒辦法區(qū)分。

2. 引用

2.1 引用的概念

引用不是新定義一個(gè)變量,而是給已存在變量取一個(gè)別名,編譯器不會(huì)為引用變量開辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。
就像外號(hào)一樣,盡管名字不同但人都是一個(gè)人。
語(yǔ)法:

類型& 引用變量名(對(duì)象名) = 引用實(shí)體

#include <cstdio>
void test()
{
	int a = 10;
	int& ra = a;//定義引用類型
	printf("%p\n", &a);
	printf("%p\n", &ra);
}
int main()
{
	test();
	return 0;
}
//打印結(jié)果:
/*
009EFDE0
009EFDE0
*/

注意:引用類型必須和引用實(shí)體是同種類型的。

2.2 引用的特性

  • 引用在定義時(shí)必須初始化。
  • 一個(gè)變量可以有多個(gè)引用。
  • 引用一旦引用一個(gè)實(shí)體,就不能再引用其他實(shí)體。
void test()
{
	int a = 10;
	//int& ra;//引用在定義時(shí)必須初始化,否則報(bào)錯(cuò)
	int& ra = a;
	int& rra = a;
	printf("%p\n", &a);
	printf("%p\n", &ra);
	printf("%p\n", &rra);
}
//打印結(jié)果:
/*
00AFF9A0
00AFF9A0
00AFF9A0
*/

2.3 常引用

void testconstref()
{
	const int a = 10;
	//int& ra = a;//該語(yǔ)句編譯時(shí)會(huì)出錯(cuò),a為常量
	const int& ra = a;
	//int& b = 10;//該語(yǔ)句編譯時(shí)會(huì)出錯(cuò),10為常量
	const int& b = 10;
	double d = 3.14;
	//int& rd = d;該語(yǔ)句編譯時(shí)會(huì)出錯(cuò),類型不同
	const int& rd = d;
}

2.4 使用場(chǎng)景

做參數(shù)

void Swap(int& left,int& right)
{
	int temp = left;
	left = right;
	right = temp;
}

做返回值

int& Count()
{
	static int n = 0;
	n++;
	//...
	return n;
}

觀察下來代碼,會(huì)輸出什么結(jié)果?

#include <iostream>
using namespace std;
int& add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = add(2, 3);
	add(4, 5);
	cout << "add(2,3) is :" << ret << endl;
	return 0;
}
//打印結(jié)果
/*
add(2,3) is :9
*/

函數(shù)運(yùn)行時(shí),系統(tǒng)需要給函數(shù)開辟獨(dú)立的棧空間,用來保存函數(shù)的形參,局部變量以及一些寄存器信息等。
函數(shù)運(yùn)行結(jié)束后,該函數(shù)對(duì)應(yīng)的棧空間就被系統(tǒng)回收了。
空間被回收指該棧空間暫時(shí)不能使用,但是內(nèi)存還在,比如:上課申請(qǐng)教室,上完課之后教師歸還給學(xué)校,但是教室本身還在,不能說歸還后,教室就消失了。

注意:如果函數(shù)返回了,出了函數(shù)作用域,如果返回對(duì)象還在(沒有還給系統(tǒng)),則可以使用引用返回,如果已經(jīng)還給系統(tǒng)了,則必須使用傳值返回。

2.5 傳值、傳引用效率比較

以值作為參數(shù)或者返回類型,在傳參和返回期間,函數(shù)不會(huì)直接傳遞實(shí)參或者將變量本身直接返回,而是傳遞實(shí)參或者返回變量的一份臨時(shí)拷貝,因此用值作為參數(shù)或者返回類型,效率是非常低下的,尤其是當(dāng)參數(shù)或返回類型非常大時(shí),效率就更低。

演示:效率對(duì)比,值和引用作為參數(shù)類型的性能對(duì)比

#include <iostream>
#include <ctime>
using namespace std;
struct  A
{
	int a[10000];
};
void TestFunc(A a)
{
}
void TestFunc2(A& a)
{
}
int main()
{
	A a;
	//以值作為函數(shù)參數(shù)
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; ++i)
	{
		TestFunc(a);
	}
	size_t end1 = clock();
	//以引用作為函數(shù)參數(shù)
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
	{
		TestFunc2(a);
	}
	size_t end2 = clock();
	//分別計(jì)算兩個(gè)函數(shù)運(yùn)行結(jié)束后的時(shí)間
	cout << "Testfunc(A) time:" << end1 - begin1 << endl;
	cout << "Testfunc2(A&) time:" << end2 - begin2 << endl;
	return 0;
}
//打印結(jié)果        
/*
Testfunc(A) time:12
Testfunc2(A&) time:0
(單位毫秒)
*/

演示:值和引用的作為返回類型的性能對(duì)比

#include <iostream>
#include <ctime>
using namespace std;
struct  A
{
	int a[10000];
};
struct A a;
//值返回
A TestFunc()
{
	return a;
}
//引用返回
A& TestFunc2()
{
	return a;
}
int main()
{
	//以值作為函數(shù)的返回類型
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; ++i)
	{
		TestFunc();
	}
	size_t end1 = clock();
	//以引用作為函數(shù)的返回類型
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
	{
		TestFunc2();
	}
	size_t end2 = clock();
	//分別計(jì)算兩個(gè)函數(shù)運(yùn)行結(jié)束后的時(shí)間
	cout << "Testfunc(A) time:" << end1 - begin1 << endl;
	cout << "Testfunc2(A&) time:" << end2 - begin2 << endl;
	return 0;
}
//打印結(jié)果
/*
Testfunc(A) time:25
Testfunc2(A&) time:1
*/

結(jié)論:通過上述的代碼可以清楚的發(fā)現(xiàn),傳值和傳引用在作為傳參以及返回值類型上效率相差很大。

2.6 引用和指針的區(qū)別

在語(yǔ)法層面上呢,引用就是一個(gè)別名,沒有獨(dú)立空間,和其被引用體共用一塊空間。

#include <iostream>
using namespace std;
int main()
{
	int val = 100;
	int& rval = val;
	cout<<"&val = "<<&val<<endl;
	cout<<"&rval = "<<&rval<<endl;
	return 0;
}
//打印結(jié)果
/*
&val = 003AFB98
&rval = 003AFB98
*/

但是呢,在底層方面實(shí)際是由空間的,因?yàn)橐檬前凑罩羔樂绞絹韺?shí)現(xiàn)的。

#include <iostream>
using namespace std;
int main()
{
	int a = 10;
	int& ra = a;
	ra = 20;
	int* pa = &a;
	*pa = 20
	return 0;
}

反匯編:

可以看到操作是類似的。
引用和指針的不同點(diǎn):

  • 引用概念上定義一個(gè)變量的別名,指針存儲(chǔ)一個(gè)變量地址。
  • 引用在定義時(shí)必須初始化,指針就沒有要求。
  • 引用在初始化時(shí)引用一個(gè)實(shí)體后,就不能再引用其他實(shí)體,而指針可以再任何時(shí)候指向任何一個(gè)同類型實(shí)體。
  • 沒有NULL引用,但是又NULL指針
  • 再sizeof中含義不同:引用結(jié)果為引用類型的大小,但是指針始終是地址空間所占字節(jié)數(shù)個(gè)(根據(jù)所在平臺(tái)確定,如32位平臺(tái)占4個(gè)字節(jié))
  • 引用自加即引用的實(shí)體加1,指針自加即指針向后偏移一個(gè)類型的大小。
  • 由多級(jí)指針,但是沒有多級(jí)引用。
  • 訪問實(shí)體方式不同,指針需要顯示解引用,引用編譯器自己處理。
  • 引用比指針使用起來相對(duì)安全。

到此這篇關(guān)于C++中函數(shù)重載與引用的的文章就介紹到這了,更多相關(guān)C++函數(shù)重載與引用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)快速排序算法實(shí)例

    C語(yǔ)言實(shí)現(xiàn)快速排序算法實(shí)例

    快速排序時(shí)間復(fù)雜度為O(nlogn),是數(shù)組相關(guān)的題目當(dāng)中經(jīng)常會(huì)用到的算法,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言實(shí)現(xiàn)快速排序算法的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷游戲

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++實(shí)現(xiàn)在文本中找出某個(gè)單詞的位置信息

    C++實(shí)現(xiàn)在文本中找出某個(gè)單詞的位置信息

    本文給大家分享的是使用C++實(shí)現(xiàn)在文本中找出某個(gè)單詞的位置信息,就是給出此單詞所在的行和列,有需要的小伙伴可以參考下。
    2016-02-02
  • C++如何在一個(gè)函數(shù)內(nèi)返回不同類型(三種方法)

    C++如何在一個(gè)函數(shù)內(nèi)返回不同類型(三種方法)

    C++?中要在一個(gè)函數(shù)內(nèi)返回不同類型的值,你可以使用?C++17?引入的?std::variant?或?std::any,或者使用模板和多態(tài),下面將分別介紹這些方法,需要的朋友可以參考下
    2023-12-12
  • codeblocks 對(duì)‘cv::waitKey(int)’未定義的引用方式

    codeblocks 對(duì)‘cv::waitKey(int)’未定義的引用方式

    今天小編就為大家分享一篇codeblocks 對(duì)‘cv::waitKey(int)’未定義的引用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • C++檢查某個(gè)文件或目錄是否存在的函數(shù)

    C++檢查某個(gè)文件或目錄是否存在的函數(shù)

    這篇文章主要介紹了C++檢查某個(gè)文件或目錄是否存在的函數(shù),是Windows應(yīng)用程序設(shè)計(jì)中非常常見的實(shí)用技巧,需要的朋友可以參考下
    2014-10-10
  • C++實(shí)現(xiàn)加減乘除計(jì)算器

    C++實(shí)現(xiàn)加減乘除計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)加減乘除計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下<BR>
    2022-01-01
  • C++詳細(xì)講解函數(shù)調(diào)用與Struct和CLass的區(qū)別

    C++詳細(xì)講解函數(shù)調(diào)用與Struct和CLass的區(qū)別

    主調(diào)函數(shù)使用被調(diào)函數(shù)的功能,稱為函數(shù)調(diào)用。在C語(yǔ)言/C++中,只有在函數(shù)調(diào)用時(shí),函數(shù)體中定義的功能才會(huì)被執(zhí)行,下面讓我們?cè)敿?xì)來了解
    2022-05-05
  • c++中struct使用注意事項(xiàng)

    c++中struct使用注意事項(xiàng)

    本文通過2個(gè)小示例給大家展示了一下c++中struct使用的注意事項(xiàng),希望對(duì)大家學(xué)習(xí)C++能夠有所幫助。
    2016-01-01
  • C/C++利用libxml2高效輸出XML大文件詳解

    C/C++利用libxml2高效輸出XML大文件詳解

    這篇文章主要給大家介紹了關(guān)于C/C++利用libxml2高效輸出XML大文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11

最新評(píng)論

郯城县| 新宾| 绥棱县| 灌阳县| 武平县| 邯郸县| 本溪市| 雷山县| 勃利县| 大冶市| 深州市| 六枝特区| 东乡族自治县| 永昌县| 延津县| 涪陵区| 平凉市| 鄂尔多斯市| 文成县| 武安市| 峨眉山市| 浦东新区| 鹿邑县| 山东省| 靖宇县| 尖扎县| 鹤峰县| 政和县| 沛县| 开阳县| 炎陵县| 江津市| 安吉县| 台北县| 稻城县| 若羌县| 新建县| 舟曲县| 中方县| 通许县| 喜德县|