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

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

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

1. 函數(shù)重載

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

1.1 函數(shù)重載概念

函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個功能類似的同名函數(shù),這些函數(shù)的形參列表(參數(shù)個數(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ù)個數(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語言不支持函數(shù)重載呢?
在C/C++中,一個程序要運(yùn)行起來,需要經(jīng)歷以下幾個階段:預(yù)處理、編譯、匯編、鏈接。

  • 實際項目中通常是由多個頭文件和多個源文件構(gòu)成的,而通過C語言階段學(xué)習(xí)的編譯鏈接,我們可以知道,【當(dāng)前a.cpp中調(diào)用了b.cpp中定義的Add函數(shù)時】,編譯后鏈接前,a.o的目標(biāo)文件中沒有Add的函數(shù)地址,因為Add是在b.cpp中定義的,所以Add的地址在b.o中。那么怎么辦呢?
  • 所以鏈接階段就是專門處理這種問題的,鏈接器看到a.o調(diào)用Add,但是沒有Add的地址,就會到b.o的符號表中找Add的地址,然后鏈接到一起。
  • 那么鏈接時,面對Add函數(shù),鏈接器會使用哪個名字去找呢?這里每個編譯器都有自己的函數(shù)名修飾規(guī)則。
  • 由于windows下vs的修飾規(guī)則過于復(fù)雜,而Linux下g++的修飾規(guī)則簡單易懂,下面我們使用了g++演示這個修飾后的名字。
  • 通過下面我們可以看到gcc的函數(shù)修飾后名字不變。而g++的函數(shù)修飾后變成【__Z+函數(shù)長度+函數(shù)名+類型首字母】
  • 采用C語言編譯器編譯后的結(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é):對比Linux會發(fā)現(xiàn),Windows下vs編譯器對函數(shù)名字修飾規(guī)則相對復(fù)雜難懂,但道理類似。
6. 通過這里就理解了C語言沒辦法支持重載,因為同名函數(shù)沒辦法區(qū)分。而C++是通過函數(shù)修飾規(guī)則來區(qū)分地,只要參數(shù)不同,修飾出來地名字就不一樣,那么就可以支持重載了。
7. 如果兩個函數(shù)函數(shù)名和參數(shù)是一樣的,返回值不同是不構(gòu)成重載的,因為調(diào)用時編譯器沒辦法區(qū)分。

2. 引用

2.1 引用的概念

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

類型& 引用變量名(對象名) = 引用實體

#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
*/

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

2.2 引用的特性

  • 引用在定義時必須初始化。
  • 一個變量可以有多個引用。
  • 引用一旦引用一個實體,就不能再引用其他實體。
void test()
{
	int a = 10;
	//int& ra;//引用在定義時必須初始化,否則報錯
	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;//該語句編譯時會出錯,a為常量
	const int& ra = a;
	//int& b = 10;//該語句編譯時會出錯,10為常量
	const int& b = 10;
	double d = 3.14;
	//int& rd = d;該語句編譯時會出錯,類型不同
	const int& rd = d;
}

2.4 使用場景

做參數(shù)

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

做返回值

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

觀察下來代碼,會輸出什么結(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)行時,系統(tǒng)需要給函數(shù)開辟獨立的??臻g,用來保存函數(shù)的形參,局部變量以及一些寄存器信息等。
函數(shù)運(yùn)行結(jié)束后,該函數(shù)對應(yīng)的??臻g就被系統(tǒng)回收了。
空間被回收指該??臻g暫時不能使用,但是內(nèi)存還在,比如:上課申請教室,上完課之后教師歸還給學(xué)校,但是教室本身還在,不能說歸還后,教室就消失了。

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

2.5 傳值、傳引用效率比較

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

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

#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();
	//分別計算兩個函數(shù)運(yùn)行結(jié)束后的時間
	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
(單位毫秒)
*/

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

#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();
	//分別計算兩個函數(shù)運(yùn)行結(jié)束后的時間
	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ū)別

在語法層面上呢,引用就是一個別名,沒有獨立空間,和其被引用體共用一塊空間。

#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
*/

但是呢,在底層方面實際是由空間的,因為引用是按照指針方式來實現(xiàn)的。

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

反匯編:

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

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

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

相關(guān)文章

  • C++的new和delete使用示例詳解

    C++的new和delete使用示例詳解

    這篇文章主要為大家介紹了C++的new和delete使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 基于C語言實現(xiàn)簡易的掃雷游戲

    基于C語言實現(xiàn)簡易的掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了基于C語言實現(xiàn)簡易的掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言計算1/1+1/2+1/3+…+1/n的問題

    C語言計算1/1+1/2+1/3+…+1/n的問題

    這篇文章主要介紹了C語言計算1/1+1/2+1/3+…+1/n的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言進(jìn)階之字符串查找?guī)旌瘮?shù)詳解

    C語言進(jìn)階之字符串查找?guī)旌瘮?shù)詳解

    字符串是一種非常重要的數(shù)據(jù)類型,但是C語言不存在顯式的字符串類型,C語言中的字符串都以字符串常量的形式出現(xiàn)或存儲在字符數(shù)組中,下面這篇文章主要給大家介紹了關(guān)于C語言進(jìn)階之字符串查找?guī)旌瘮?shù)的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • C語言之整數(shù)劃分問題(遞歸法)實例代碼

    C語言之整數(shù)劃分問題(遞歸法)實例代碼

    這篇文章主要介紹了C語言之整數(shù)劃分問題(遞歸法)實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • C語言大小端模式、判斷大小端、大小端轉(zhuǎn)換方法詳解

    C語言大小端模式、判斷大小端、大小端轉(zhuǎn)換方法詳解

    這篇文章主要介紹了C語言大小端模式、判斷大小端、大小端轉(zhuǎn)換的相關(guān)資料,大端和小端是數(shù)據(jù)在內(nèi)存中的存儲方式,大端模式下高字節(jié)存于低地址,小端模式則相反,大小端問題由數(shù)據(jù)類型多字節(jié)存儲引起,不同選擇形成不同存儲模式,需要的朋友可以參考下
    2024-10-10
  • 基于C++ list中erase與remove函數(shù)的使用詳解

    基于C++ list中erase與remove函數(shù)的使用詳解

    本篇文章是對C++ list中erase與remove函數(shù)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++如何調(diào)用已經(jīng)寫好的C接口

    C++如何調(diào)用已經(jīng)寫好的C接口

    如何在C++代碼中調(diào)用寫好的C接口?你可能會奇怪,C++不是兼容C嗎?直接調(diào)用不就可以了,那么我們來測試一下,先看看C++如何調(diào)用C代碼接口的,需要的朋友可以參考一下
    2021-10-10
  • C++基本算法思想之窮舉法

    C++基本算法思想之窮舉法

    在使用窮舉法時,需要明確問題的答案的范圍,這樣才可以在指定的范圍內(nèi)搜索答案。指定范圍之后,就可以使用循環(huán)語句和條件語句逐步驗證候選答案的正確性,從而得到需要的正確答案
    2013-10-10
  • C++二級指針和指針的引用

    C++二級指針和指針的引用

    這篇文章主要介紹了C++二級指針和指針的引用,下文舉例實現(xiàn)形參指針改變實參指針?biāo)赶虻膶ο?,需要的小伙伴可以參考一下,希望對你的學(xué)習(xí)有所幫助
    2022-03-03

最新評論