[Einführung in C++ Teil 3] Lernen Sie die C++-Standardparameter kennen | Funktionsüberladung | Zitat

1.Standardparameter

1.1 Konzept der Standardparameter

Standardparameter geben einen Standardwert für die Parameter der Funktion an, wenn eine Funktion deklariert oder definiert wird. Wenn beim Aufruf dieser Funktion kein Aktualparameter angegeben wird, wird der Standardwert des Formalparameters verwendet, andernfalls wird der angegebene Aktualparameter verwendet.

void Func(int a = 0)
{
    
    
 cout<<a<<endl;
}
int main()
{
    
    
 Func();     // 没有传参时,使用参数的默认值
 Func(10);   // 传参时,使用指定的实参
return 0;
}

1.2 Standardparameterklassifizierung

①Alle Standardparameter

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

②Semi-Standardparameter

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

注意:

1. 半缺省参数必须从右往左依次来给出,不能间隔着给
2. 缺省参数不能在函数声明和定义中同时出现

 //a.h
  void Func(int a = 10);
  
  // a.cpp
  void Func(int a = 20)
 {
    
    }
  
  // 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,
 //那编译器就无法确定到底该用那个缺省值

3. 缺省值必须是常量或者全局变量
4. C语言不支持(编译器不支持)



2. Funktionsüberlastung

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。
Zum Beispiel: Früher gab es den Witz, dass man sich die beiden staatlichen Sportarten nicht anschauen oder sich um sie kümmern müsse. Das eine ist Tischtennis und das andere ist Männerfußball. Ersteres ist „Niemand kann gewinnen!“ und Letzteres ist „Niemand kann gewinnen!“


2.1 Konzept der Funktionsüberladung

函数重载: ist ein Sonderfall von Funktionen. In C++ können Sie mehrere Funktionen mit demselben Namen mit ähnlichen Funktionen im selben Bereich deklarieren. Die formalen Parameterlisten dieser Funktionen mit demselben Namen sind unterschiedlich. (参数个数 或 类型 或 类型顺序) wird häufig verwendet, um damit umzugehen. Implementieren Sie Funktionen, die dem Problem verschiedener Datentypen ähneln.

#include<iostream>
using namespace std;

// 1、参数类型不同
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、参数个数不同
void f()
{
    
    
 cout << "f()" << endl;
}
void f(int a)
{
    
    
 cout << "f(int a)" << endl;
}

// 3、参数类型顺序不同
void f(int a, char b)
{
    
    
 cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
    
    
 cout << "f(char b, int a)" << endl;
}
int main()
{
    
    
 Add(10, 20);
 Add(10.1, 20.2);
 f();
 f(10);
 f(10, 'a');
 f('a', 10);
 return 0;
}

2.2 Das Prinzip der C++-Unterstützung der Funktionsüberladung – Namensverzerrung

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
Fügen Sie hier eine Bildbeschreibung ein


abschließend:

1.通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

2. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。



3. Zitat

3.1 Referenzkonzept

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间。


比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

Fügen Sie hier eine Bildbeschreibung ein
Typ und Referenzvariablenname (Objektname) = Referenzentität;

void TestRef()
{
    
    
    int a = 10;
    int& ra = a;//<====定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}

注意:①引用类型必须和引用实体是同种类型的、 ② 引用必须进行初始化


3.2 Zitiermerkmale

  1. Referenzen müssen bei der Definition initialisiert werden
  2. Eine Variable kann mehrere Referenzen haben
  3. Sobald sich eine Referenz auf eine Entität bezieht, kann sie nicht auf andere Entitäten verweisen.
void TestRef()
{
    
    
   int a = 10;
   // int& ra;   // 该条语句编译时会出错
   int& ra = a;
   int& rra = a;
   printf("%p %p %p\n", &a, &ra, &rra);  
}

3.3 Häufig zitiert

void TestConstRef()
{
    
    
    const int a = 10;
    //int& ra = a;   // 该语句编译时会出错,a为常量
    const int& ra = a;
    // int& b = 10; // 该语句编译时会出错,b为常量
    const int& b = 10;
    double d = 12.34;
    //int& rd = d; // 该语句编译时会出错,类型不同
    const int& rd = d;
}

3.4 Nutzungsszenarien

1. Parameter erstellen

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

2. Rückgabewert festlegen

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

Hinweis: Wenn die Funktion außerhalb des Funktionsbereichs zurückkehrt und das zurückgegebene Objekt noch vorhanden ist (es wurde nicht an das System zurückgegeben), können Sie die Referenzrückgabe verwenden. Wenn es an das System zurückgegeben wurde, müssen Sie die Wertrückgabe verwenden .


3.5 Vergleich der Effizienz der Wertübergabe und der Referenzübergabe

Verwenden Sie einen Wert als Parameter oder Rückgabewerttyp. Während der Parameterübergabe und -rückgabe übergibt die Funktion die tatsächlichen Parameter nicht direkt oder gibt die Variable selbst direkt zurück. Stattdessen übergibt sie die tatsächlichen Parameter oder gibt eine temporäre Kopie der Variablen zurück. Verwenden Sie also den Wert als Parameter oder den Rückgabewerttyp, die Effizienz ist sehr gering, insbesondere wenn der Parameter oder Rückgabewerttyp sehr groß ist, ist die Effizienz noch geringer.

#include <time.h>
struct A{
    
     int a[10000]; };
void TestFunc1(A a){
    
    }
void TestFunc2(A& a){
    
    }
void TestRefAndValue()
{
    
    
 A a;
 // 以值作为函数参数
 size_t begin1 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc1(a);
 size_t end1 = clock();
 // 以引用作为函数参数
 size_t begin2 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc2(a);
 size_t end2 = clock();
// 分别计算两个函数运行结束后的时间
 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
 cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

#include <time.h>
struct A{
    
     int a[10000]; };
A a;
// 值返回
A TestFunc1() {
    
     return a;}
// 引用返回
A& TestFunc2(){
    
     return a;}
void TestReturnByRefOrValue()
{
    
    
 // 以值作为函数的返回值类型
 size_t begin1 = clock();
 for (size_t i = 0; i < 100000; ++i)
 TestFunc1();
 size_t end1 = clock();
 // 以引用作为函数的返回值类型
 size_t begin2 = clock();
 for (size_t i = 0; i < 100000; ++i)
 TestFunc2();
 size_t end2 = clock();
 // 计算两个函数运算完成之后的时间
 cout << "TestFunc1 time:" << end1 - begin1 << endl;
 cout << "TestFunc2 time:" << end2 - begin2 << endl;
}

Durch den Vergleich der oben genannten Codes wurde festgestellt, dass die Effizienz der Übergabe von Werten und Zeigern als Parameter und Rückgabewerttypen sehr unterschiedlich ist.



3.6 Der Unterschied zwischen Referenzen und Zeigern

Im grammatikalischen Konzept ist eine Referenz ein Alias, der keinen unabhängigen Raum hat und denselben Raum mit der Entität teilt, auf die er verweist.

int main()
{
    
    
int a = 10;
int& ra = a;
cout<<"&a = "<<&a<<endl;
cout<<"&ra = "<<&ra<<endl;
return 0;
}

In der zugrunde liegenden Implementierung ist tatsächlich Platz vorhanden, da Referenzen in Zeigerform implementiert werden.

int main()
{
    
    
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
return 0;
}

Werfen wir einen Blick auf den Assembler-Code-Vergleich von Referenzen und Zeigern:

Fügen Sie hier eine Bildbeschreibung ein

4. Zusammenfassung der Unterschiede zwischen Referenzen und Zeigern

  1. Eine Referenz definiert konzeptionell einen Alias ​​für eine Variable und ein Zeiger speichert eine Variablenadresse.
  2. Referenzen müssen bei der Definition initialisiert werden, Zeiger sind nicht erforderlich
  3. Nachdem eine Referenz während der Initialisierung auf eine Entität verweist, kann sie nicht mehr auf andere Entitäten verweisen, und ein Zeiger kann jederzeit auf eine beliebige Entität desselben Typs verweisen.
  4. Keine NULL-Referenz, sondern NULL-Zeiger
  5. Die Bedeutung von sizeof ist unterschiedlich: Das Referenzergebnis ist die Größe des Referenztyps, der Zeiger ist jedoch immer die Anzahl der vom Adressraum belegten Bytes (4 Bytes auf einer 32-Bit-Plattform).
  6. Die Selbstinkrementierung der Referenz bedeutet, dass die referenzierte Entität um 1 erhöht wird, und die Selbstinkrementierung des Zeigers bedeutet, dass der Zeiger um die Größe des Typs nach hinten versetzt wird.
  7. Es gibt mehrstufige Zeiger, aber keine mehrstufigen Referenzen
  8. Der Zugriff auf Entitäten ist unterschiedlich: Der Zeiger muss explizit dereferenziert werden, und der Referenz-Compiler verarbeitet dies selbst.
  9. Referenzen sind relativ sicherer zu verwenden als Zeiger

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

Supongo que te gusta

Origin blog.csdn.net/qq_58286439/article/details/134179386
Recomendado
Clasificación