国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++】main開始的地方

這篇具有很好參考價值的文章主要介紹了【C++】main開始的地方。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

1. C++關鍵字

2. 命名空間

2.1 命名空間定義

2.2 命名空間使用

3. C++輸入&輸出

4. 缺省參數

4.1 缺省參數概念

4.2 缺省參數分類

5. 函數重載

5.1 函數重載概念

5.2 C++支持函數重載的原理--名字修飾(name Mangling)

6. 引用

6.1 引用概念

6.2 引用特性

6.3 常引用

6.4 使用場景

6.5 傳值、傳引用效率比較

6.5.1 值和引用作為函數參數的性能比較

6.5.2 值和引用作為返回值類型的性能比較

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

7. 內聯函數

7.1 概念

7.2 特性

8. auto關鍵字(C++11)

8.1 類型別名思考

8.2 auto簡介

8.3 auto的使用細則

8.4?auto不能推導的場景

9. 基于范圍的for循環(huán)(C++11)

9.1 范圍for的語法

9.2 范圍for的使用條件

10. 指針空值nullptr(C++11)

10.1 C++98中的指針空值


1. C++關鍵字

C++總計63個關鍵字,C語言32個關鍵字

ps:下面我們只是看一下C++有多少關鍵字,不對關鍵字進行具體的講解。

asm do if return try continue
auto double inline short typedef for
bool dynamic_cast int signed typeid public
break else long sizeof typename throw
case enum mutable static union wchar_t
catch explicit namespace static_cast unsigned default
char export new struct using friend
class extern operator switch virtual register
const false private template void true
const_cast float protected this volatile while
delete goto reinterpret_cast

2. 命名空間

在C/C++中,變量、函數和后面要學到的類都是大量存在的,這些變量、函數和類的名稱將都存在于全局作用域中,可能會導致很多沖突。使用命名空間的目的是對標識符的名稱進行本地化,以避免命名沖突或名字污染,namespace關鍵字的出現就是針對這種問題的。

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

int rand = 10;

// C語言沒辦法解決類似這樣的命名沖突問題,所以C++提出了namespace來解決
int main()
{
	printf("%d\n", rand);
	return 0;
}

// 編譯后后報錯:error C2365: “rand”: 重定義;以前的定義是“函數”

2.1 命名空間定義

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

// tjq是命名空間的名字,一般開發(fā)中是用項目名字做命名空間名。
// 1. 正常的命名空間定義
namespace tjq
{
	// 命名空間中可以定義變量/函數/類型
	int rand = 10;

	int Add(int left, int right)
	{
		return left + right;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}

//2. 命名空間可以嵌套
// test.cpp
namespace N1
{
	int a;
	int b;
	int Add(int left, int right)
	{
		return left + right;
	}

	namespace N2
	{
		int c;
		int d;
		int Sub(int left, int right)
		{
			return left - right;
		}
	}
}

//3. 同一個工程中允許存在多個相同名稱的命名空間,編譯器最后會合成同一個命名空間中。
// ps:一個工程中的test.h和上面test.cpp中兩個N1會被合并成一個
// test.h
namespace N1
{
	int Mul(int left, int right)
	{
		return left * right;
	}
}

注意:一個命名空間就定義了一個新的作用域,命名空間中的所有內容都局限于該命名空間中。

2.2 命名空間使用

命名空間中成員該如何使用呢?比如:

namespace N
{
	// 命名空間中可以定義變量/函數/類型
	int a = 0;
	int b = 1;

	int Add(int left, int right)
	{
		return left + right;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}

int main()
{
	// 編譯報錯:error C2065: “a”: 未聲明的標識符
	printf("%d\n", a);
	return 0;
}

命名空間的使用有三種方式:

  • 加命名空間名稱及作用域限定符
int main()
{
	printf("%d\n", N::a);
	return 0;
}
  • 使用using將命名空間中某個成員引入
using N::b;
int main()
{
	printf("%d\n", N::a);
	printf("%d\n", b);
	return 0;
}
  • 使用using namespace命名空間名稱引入
using namespce N;
int main()
{
	printf("%d\n", N::a);
	printf("%d\n", b);
	Add(10, 20);
	return 0;
}

3. C++輸入&輸出

新生嬰兒會以自己獨特的方式向這個嶄新的世界打招呼,C++剛出來后,也算是一個新事物,那C++是否也應該向這個美好的世界來聲問候呢?我們來看下C++是如何來實現問候的。

#include <iostream>
// std是C++標準庫的命名空間名,C++將標準庫的定義實現都放到這個命名空間中
using namespace std;

int main()
{
	cout << "Hello world!!!" << endl;
	return 0;
}

說明:

  1. 使用cout標準輸出對象(控制臺)cin標準輸入對象(鍵盤)時,必須包含<iostream>頭文件以及按命名空間使用方法使用std。
  2. cout和cin是全局的流對象,endl是特殊的C++符號,表示換行輸出,他們都包含在<iostream>頭文件中。
  3. <<是流插入運算符,>>是流提取運算符。
  4. 使用C++輸入輸出更方便,不需要像printf/scanf輸入輸出時那樣,需要手動控制格式。C++的輸入輸出可以自動識別變量類型。
  5. 實際上cout和cin分別是ostream和istream類型的對象,>>和<<也涉及運算符重載等知識,這些知識我們我們后續(xù)才會學習,所以我們這里只是簡單學習他們的使用。后面我們還有一個章節(jié)更深入的學習IO流用法及原理。

注意:早期標準庫將所有功能在全局域中實現,聲明在.h后綴的頭文件中,使用時只需包含對應頭文件即可,后來將其實現在std命名空間下,為了和C頭文件區(qū)分,也為了正確使用命名空間,規(guī)定C++頭文件不帶.h;舊編譯器(vc 6.0)中還支持<iostream.h>格式,后續(xù)編譯器已不支持,因此推薦使用<iostream>+std的方式。

#include <iostream>
using namespace std;

int main()
{
	int a;
	double b;
	char c;

	// 可以自動識別變量的類型
	cin >> a;
	cin >> b >> c;

	cout << a << endl;
	cout << b << " " << c << endl;
	return 0;
}

// ps:關于cout和cin還有很多更復雜的用法,比如控制浮點數輸出精度,控制整形輸出進制格式等
// 等。因為C++兼容C語言的用法,這些又用得不是很多,我們這里就不展開學習了。

std命名空間的使用慣例:

std是C++標準庫的命名空間,如何展開std使用更合理呢?

  1. 在日常練習中,建議直接using namespace std即可,這樣就很方便。
  2. using namespace std展開,標準庫就全部暴露出來了,如果我們定義跟庫重名的類型/對象/函數,就存在沖突問題。該問題在日常練習中很少出現,但是項目開發(fā)中代碼較多、規(guī)模大,就很容易出現。所以建議在項目開發(fā)中使用,像std::cout這樣使用時指定命名空間 + using std::cout展開常用的庫對象/類型等方式。

4. 缺省參數

4.1 缺省參數概念

缺省參數是聲明或定義函數時為函數的參數指定一個缺省值。在調用該函數時,如果沒有指定實參則采用該形參的缺省值,否則使用指定的實參。

void Func(int a = 0)
{
	cout << a << endl;
}

int main()
{
	Func();      // 沒有傳參時,使用參數的默認值
	Func(10);    // 傳參時,使用指定的實參
	return 0;
}

4.2 缺省參數分類

  • 全缺省參數
void Func(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}
  • 半缺省參數
void Func(int a, int b = 10, int c = 20)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

注意:

????????1.?半缺省參數必須從右往左依次來給出,不能間隔著給

? ? ? ? 2.?缺省參數不能在函數聲明和定義中同時出現

// test.h
void Func(int a = 10);

// test.cpp
void Func(int a = 20)
{}

// 注意:如果生命與定義位置同時出現,恰巧兩個位置提供的值不同,那編譯器就無法確定到底該
// 用那個缺省值。

? ? ? ? 3. 缺省值必須是常量或者全局變量

? ? ? ? 4. C語言不支持(編譯器不支持)

5. 函數重載

自然語言中,一個詞可以有多重含義,人們可以通過上下文來判斷該詞真實的含義,即該詞被重載了。

比如:以前有一個笑話,國有兩個體育項目大家根本不用看,也不用擔心。一個是乒乓球,一個
是男足。前者是“誰也贏不了!”,后者是“誰也贏不了!”

5.1 函數重載概念

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

#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;
}

5.2 C++支持函數重載的原理--名字修飾(name Mangling)

為什么C++支持函數重載,而C語言不支持函數重載呢?

在C/C++中,一個程序要運行起來,需要經歷以下幾個階段:預處理、編譯、匯編、鏈接。

【C++】main開始的地方,C++,c++,開發(fā)語言

【C++】main開始的地方,C++,c++,開發(fā)語言

????????1. 實際項目通常是由多個頭文件和多個源文件構成,而通過C語言階段學習的編譯鏈接,我們可以知道,【當前a.cpp中調用了b.cpp中定義的Add函數時】,編譯后鏈接前,a.o的目標文件中沒有Add的函數地址,因為Add是在b.cpp中定義的,所以Add的地址在b.o中。那么怎么辦呢?

????????2.?所以鏈接階段就是專門處理這種問題,鏈接器看到a.o調用Add,但是沒有Add的地址,就會到b.o的符號表中找Add的地址,然后鏈接到一起。

????????3.?那么鏈接時,面對Add函數,鏈接接器會使用哪個名字去找呢?這里每個編譯器都有自己的函數名修飾規(guī)則。

????????4.?由于Windows下vs的修飾規(guī)則過于復雜,而Linux下g++的修飾規(guī)則簡單易懂,下面我們使用了g++演示了這個修飾后的名字。

????????5.?通過下面我們可以看出gcc的函數修飾后名字不變。而g++的函數修飾后變成【_Z+函數長度+函數名+類型首字母】。

  • 采用C語言編譯器編譯后結果

【C++】main開始的地方,C++,c++,開發(fā)語言

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

  • 采用C++編譯器編譯后結果

【C++】main開始的地方,C++,c++,開發(fā)語言

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

  • Windows下名字修飾規(guī)則

【C++】main開始的地方,C++,c++,開發(fā)語言

對比Linux會發(fā)現,windows下vs編譯器對函數名字修飾規(guī)則相對復雜難懂,但道理都是類似的,這里就不深究了。

????????6.?通過這里就理解了C語言沒辦法支持重載,因為同名函數沒辦法區(qū)分。而C++是通過函數修飾規(guī)則來區(qū)分,只要參數不同,修飾出來的名字就不一樣,就支持了重載

????????7.?如果兩個函數函數名和參數是一樣的,返回值不同是不構成重載的,因為調用時編譯器沒辦法區(qū)分。

6. 引用

6.1 引用概念

引用不是新定義一個變量,而是給已存在變量取了一個別名,編譯器不會為引用變量開辟內存空間,它和它引用的變量共用同一塊內存空間

比如:李逵,在家稱為"鐵牛",江湖上人稱"黑旋風"。

【C++】main開始的地方,C++,c++,開發(fā)語言

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

void TestRef()
{
	int a = 10;
	int& ra = a;// <==== 定義引用類型

	printf("%p\n", &a);
	printf("%p\n", &ra);
    // a 和 ra 的地址是一樣的
}

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

6.2 引用特性

  1. 引用在定義時必須初始化
  2. 一個變量可以有多個引用
  3. 引用一旦引用一個實體,再不能引用其他實體
void TestRef()
{
	int a = 10;
	// int& ra; // 該條語句編譯時會出錯
	int& ra = a;
	int& rra = a;
	printf("%p %p %p\n", &a, &ra, &rra);
}

6.3 常引用

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;
	// const int& rd = d; // 該語句編譯時會出錯,類型不同
	const double& rd = d;
}

6.4 使用場景

1. 做參數

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

2. 做返回值

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

下面代碼輸出什么結果?為什么?

int& Add(int a, int b)
{
	int c = a + b;
	return c;
}

int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

【C++】main開始的地方,C++,c++,開發(fā)語言

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

6.5 傳值、傳引用效率比較

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

6.5.1 值和引用作為函數參數的性能比較

#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;
}

6.5.2 值和引用作為返回值類型的性能比較

#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;
}

通過上述代碼的比較,發(fā)現傳值和指針在作為傳參以及返回值類型上效率相差很大。

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

語法概念上引用就是一個別名,沒有獨立空間,和其引用實體共用同一塊空間。

int main()
{
	int a = 10;
	int& ra = a;

	cout << "&a = " << &a << endl;
	cout << "&ra = " << &ra << endl;

	return 0;
}

底層實現上實際是有空間的,因為引用是按照指針方式來實現的。

int main()
{
	int a = 10;

	int& ra = a;
	ra = 20;

	int* pa = &a;
	*pa = 20;

	return 0;
}

我們來看下引用和指針的匯編代碼對比

【C++】main開始的地方,C++,c++,開發(fā)語言

引用和指針的不同點:

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

7. 內聯函數

7.1 概念

inline修飾的函數叫做內聯函數,編譯時C++編譯器會在調用內聯函數的地方展開,沒有函數調用建立棧幀的開銷,內聯函數提升程序運行的效率。

【C++】main開始的地方,C++,c++,開發(fā)語言

如果在上述函數前增加inline關鍵字將其改成內聯函數,在編譯期間編譯器會用函數體替換函數的調用。

查看方式:

  1. 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add
  2. 在debug模式下,需要對編譯器進行設置,否則不會展開(因為debug模式下,編譯器默認不會對代碼進行優(yōu)化,以下給出vs2013的設置方式)

【C++】main開始的地方,C++,c++,開發(fā)語言

【C++】main開始的地方,C++,c++,開發(fā)語言

7.2 特性

????????1. inline是一種以空間換時間的做法,如果編譯器將函數當成內聯函數處理,在編譯階段,會用函數體替換函數調用,缺陷:可能會使目標文件變大,優(yōu)勢:少了調用開銷,提高程序運行效率。

????????2.?inline對于編譯器而言只是一個建議,不同編譯器關于inline實現機制可能不同,一般建議:將函數規(guī)模較小(即函數不是很長,具體沒有準確的說法,取決于編譯器內部實現)、不是遞歸、且頻繁調用的函數采用inline修飾,否則編譯器會忽略inline特性。下圖為《C++prime》第五版關于inline的建議:

【C++】main開始的地方,C++,c++,開發(fā)語言

????????3. inline不建議聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址
了,鏈接就會找不到。

// F.h
#include <iostream>
using namespace std;

inline void f(int i);

// F.cpp
#include "F.h"
void f(int i)
{
	cout << i << endl;
}

// main.cpp
#include "F.h"
int main()
{
	f(10);
	return 0;
}

// 鏈接錯誤:main.obj : error LNK2019: 無法解析的外部符號 "void __cdecl
f(int)" (?f@@YAXH@Z),該符號在函數 _main 中被引用

8. auto關鍵字(C++11)

8.1 類型別名思考

隨著程序越來越復雜,程序中用到的類型也越來越復雜,經常體現在:

  1. 類型難于拼寫
  2. 含義不明確導致容易出錯
#include <string>
#include <map>

int main()
{
	std::map<std::string, std::string> m{ { "apple", "蘋果" }, { "orange",
	"橙子" }, { "pear","梨" } };

	std::map<std::string, std::string>::iterator it = m.begin();
	while (it != m.end())
	{
		//....
	}
	return 0;
}

std::map<std::string, std::string>::iterator 是一個類型,但是該類型太長了,特別容易寫錯。聰明的同學可能已經想到:可以通過typedef給類型取別名,比如:

#include <string>
#include <map>

typedef std::map<std::string, std::string> Map;
int main()
{
	Map m{ { "apple", "蘋果" },{ "orange", "橙子" }, {"pear","梨"} };
	Map::iterator it = m.begin();
	while (it != m.end())
	{
		//....
	}
	return 0;
}

使用typedef給類型取別名確實可以簡化代碼,但是typedef有會遇到新的難題:

typedef char* pstring;

int main()
{
	const pstring p1;    // 編譯成功還是失?。?	const pstring* p2;   // 編譯成功還是失???
	return 0;
}

在編程時,常常需要把表達式的值賦值給變量,這就要求在聲明變量的時候清楚地知道表達式的類型。然而有時候要做到這點并非那么容易,因此C++11給auto賦予了新的含義。

8.2 auto簡介

在早期C/C++中auto的含義是:使用auto修飾的變量,是具有自動存儲器的局部變量,但遺憾的是一直沒有人去使用它,大家可思考下為什么?

C++11中,標準委員會賦予了auto全新的含義即:auto不再是一個存儲類型指示符,而是作為一個新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時期推導而得。

int TestAuto()
{
	return 10;
}

int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();

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

	//auto e; 無法通過編譯,使用auto定義變量時必須對其進行初始化
	return 0;
}

【注意】

使用auto定義變量時必須對其進行初始化,在編譯階段編譯器需要根據初始化表達式來推導auto的實際類型。因此auto并非是一種“類型”的聲明,而是一個類型聲明時的“占位符”,編譯器在編譯期會將auto替換為變量實際的類型。

8.3 auto的使用細則

????????1. auto與指針和引用結合起來使用

用auto聲明指針類型時,用auto和auto*沒有任何區(qū)別,但用auto聲明引用類型時則必須加&

int main()
{
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;

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

	*a = 20;
	*b = 30;
	c = 40;

	return 0;
}

????????2. 在同一行定義多個變量

當在同一行聲明多個變量時,這些變量必須是相同的類型,否則編譯器將會報錯,因為編譯器實際只對第一個類型進行推導,然后用推導出來的類型定義其他變量

void TestAuto()
{
	auto a = 1, b = 2;
	auto c = 3, d = 4.0;    // 該行代碼會編譯失敗,因為c和d的初始化表達式類型不同
}

8.4?auto不能推導的場景

? ? ? ? 1. auto不能作為函數的參數

// 此處代碼編譯失敗,auto不能作為形參類型,因為編譯器無法對a的實際類型進行推導
void TestAuto(auto a)
{}

? ? ? ? 2. auto不能直接用來聲明數組

void TestAuto()
{
	int a[] = { 1,2,3 };
	auto b[] = { 4,5,6 };
}

????????3.?為了避免與C++98中的auto發(fā)生混淆,C++11只保留了auto作為類型指示符的用法

????????4. auto在實際中最常見的優(yōu)勢用法就是跟下面會講到的C++11提供的新式for循環(huán),還有l(wèi)ambda表達式等進行配合使用。

9. 基于范圍的for循環(huán)(C++11)

9.1 范圍for的語法

在C++98中如果要遍歷一個數組,可以按照以下方式進行:

void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
		array[i] *= 2;

	for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
		cout << *p << endl;
}

對于一個有范圍的集合而言,由程序員來說明循環(huán)的范圍是多余的,有時候還會容易犯錯誤。因此C++11中引入了基于范圍的for循環(huán)。for循環(huán)后的括號由冒號“ :”分為兩部分:第一部分是范圍內用于迭代的變量,第二部分則表示被迭代的范圍。

void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto& e : array)
		e *= 2;

	for (auto e : array)
		cout << e << " ";
}

注意:與普通循環(huán)類似,可以用continue來結束本次循環(huán),也可以用break來跳出整個循環(huán)。

9.2 范圍for的使用條件

????????1.?for循環(huán)迭代的范圍必須是確定的

對于數組而言,就是數組中第一個元素和最后一個元素的范圍;對于類而言,應該提供begin和end的方法,begin和end就是for循環(huán)迭代的范圍。

注意:以下代碼就有問題,因為for的范圍不確定

void TestFor(int array[])
{
	for (auto& e : array)
		cout << e << endl;
}

? ? ? ? 2. 迭代的對象要實現++和==的操作。(關于迭代器這個問題,以后會講,現在提一下,沒辦法講清楚,現在大家了解一下就可以了)

10. 指針空值nullptr(C++11)

10.1 C++98中的指針空值

在良好的C/C++編程習慣中,聲明一個變量時最好給該變量一個合適的初始值,否則可能會出現不可預料的錯誤,比如未初始化的指針。如果一個指針沒有合法的指向,我們基本都是按照如下方式對其進行初始化:

void TestPtr()
{
	int* p1 = NULL;
	int* p2 = 0;

	// ……
}

NULL實際是一個宏,在傳統(tǒng)的C頭文件(stddef.h)中,可以看到如下代碼:

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

可以看到,NULL可能被定義為字面常量0,或者被定義為無類型指針(void*)的常量。不論采取何種定義,在使用空值的指針時,都不可避免的會遇到一些麻煩,比如:

void f(int)
{
	cout << "f(int)" << endl;
}

void f(int*)
{
	cout << "f(int*)" << endl;
}

int main()
{
	f(0);
	f(NULL);
	f((int*)NULL);
	return 0;
}

程序本意是想通過f(NULL)調用指針版本的f(int*)函數,但是由于NULL被定義成0,因此與程序的初衷相悖。

在C++98中,字面常量0既可以是一個整形數字,也可以是無類型的指針(void*)常量,但是編譯器默認情況下將其看成是一個整形常量,如果要將其按照指針方式來使用,必須對其進行強轉(void*)0。

注意:

  1. 在使用nullptr表示指針空值時,不需要包含頭文件,因為nullptr是C++11作為新關鍵字引入的。
  2. 在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所占的字節(jié)數相同。
  3. 為了提高代碼的健壯性,在后續(xù)表示指針空值時建議最好使用nullptr。

本文完文章來源地址http://www.zghlxwxcb.cn/news/detail-739741.html

到了這里,關于【C++】main開始的地方的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 我們都低估了GPT-4,它才是夢開始的地方

    從今年開始 最近這兩個月 AI技術帶來的沖擊一個接一個 我們的團隊都在忙著研究各種AI 性能力這個方面 還真不如自己馬上上手 用這些軟件感受來的那么強烈 我覺得至少有幾個產品 大家可以去試一下 第一 大家趕緊去看一個church GBT plus的賬號 然后親身體驗一下GPT4的底層能力

    2023年04月12日
    瀏覽(19)
  • 淺談一談pytorch中模型的幾種保存方式、以及如何從中止的地方繼續(xù)開始訓練;

    一、本文總共介紹3中pytorch模型的保存方式:1.保存整個模型;2.只保存模型參數;3.保存模型參數、優(yōu)化器、學習率、epoch和其它的所有命令行相關參數以方便從上次中止訓練的地方重新啟動訓練過程。 1.保存整個模型。這種保存方式最簡單,保存內容包括模型結構、模型參數

    2024年01月17日
    瀏覽(26)
  • 從0開始,精通Go語言Rest微服務架構和開發(fā)

    從0開始,精通Go語言Rest微服務架構和開發(fā)

    現在 拿到offer超級難 ,甚至連面試電話,一個都搞不到。 尼恩的技術社區(qū)中(50+),很多小伙伴憑借 “左手云原生+右手大數據”的絕活,拿到了offer,并且是非常優(yōu)質的offer, 據說年終獎都足足18個月 。 第二個案例就是:前段時間,一個2年小伙伴希望漲薪到18K, 尼恩把

    2024年02月11日
    瀏覽(40)
  • 【Java】學習一門開發(fā)語言,從TA的Hello World開始

    【Java】學習一門開發(fā)語言,從TA的Hello World開始

    歡迎來到《小5講堂》 大家好,我是全棧小5。 這是《Java》序列文章,每篇文章將以博主理解的角度展開講解, 特別是針對知識點的概念進行敘說,大部分文章將會對這些概念進行實際例子驗證,以此達到加深對知識點的理解和掌握。 溫馨提示:博主能力有限,理解水平有限

    2024年01月23日
    瀏覽(24)
  • 【Java】十年老司機轉開發(fā)語言,新小白從學習路線圖開始

    【Java】十年老司機轉開發(fā)語言,新小白從學習路線圖開始

    歡迎來到《小5講堂》 大家好,我是全棧小5。 這是《Java》序列文章,每篇文章將以博主理解的角度展開講解, 特別是針對知識點的概念進行敘說,大部分文章將會對這些概念進行實際例子驗證,以此達到加深對知識點的理解和掌握。 溫馨提示:博主能力有限,理解水平有限

    2024年01月17日
    瀏覽(124)
  • 從0開始學C++ 第四課:常用C++編輯器和集成開發(fā)環(huán)境(IDE)的使用

    從0開始學C++ 第四課:常用C++編輯器和集成開發(fā)環(huán)境(IDE)的使用

    第四課:常用C++編輯器和集成開發(fā)環(huán)境(IDE)的使用 在這一課中,我們將了解一些流行的C++編輯器和集成開發(fā)環(huán)境(IDE),它們可以簡化C++的編寫、編譯和調試過程。我們將介紹三種流行的IDE:Visual Studio Code、Eclipse和CLion,并指導如何設置一個簡單的C++項目。 目標 了解不同

    2024年01月22日
    瀏覽(54)
  • 想從事UE4開發(fā)相關工作,C++學到什么程度可以開始學習針對虛幻4的編程開發(fā)呢?

    想從事UE4開發(fā)相關工作,C++學到什么程度可以開始學習針對虛幻4的編程開發(fā)呢?

    想從事UE4開發(fā)相關工作,C++是一個必須要熟練掌握的語言。在學習C++過程中,需要掌握語法、面向對象編程、數據結構和算法等內容,這些都是開發(fā)UE4所需要的基礎。 在掌握了C++基礎之后,可以先從UE4的官方文檔開始學習UE4的基礎知識和概念。在這里,我們可以了解到UE4的整

    2024年02月06日
    瀏覽(20)
  • 蘋果計劃 2028 年推出無人駕駛汽車;微軟開始開發(fā)小型語言模型;周鴻祎談AI

    蘋果計劃 2028 年推出無人駕駛汽車;微軟開始開發(fā)小型語言模型;周鴻祎談AI

    蘋果計劃 2028 年推出汽車 今日凌晨,據彭博社援引知情人士消息稱,之前蘋果設想要推出真正的無人駕駛汽車,而目前在開發(fā)的是自動駕駛功能更為有限的電動汽車,并推遲了發(fā)布汽車的目標日期。 蘋果公司現在計劃 2028 年推出 Lever 2+ 級別的無人駕駛汽車, 而蘋果原計劃是

    2024年01月25日
    瀏覽(23)
  • 嵌入式開發(fā)中一些需要留意的地方

    ????????使用STM32開發(fā)的朋友不知道是否有發(fā)現過這樣的一些宏定義?如下: ????????看到上面的語句一開始確實搞不懂為什么要寫這些東西,通過上網去查詢,才搞明白這其中的使用原理。 ????????上面的代碼段我們可以看到兩部分的內容: ? ? ? ? 1)__CC_ARM ?

    2024年02月06日
    瀏覽(18)
  • 從0開始,部署基于yangjianxin開發(fā)的流螢(Firefly)中文對話式大語言模型的http服務端

    從0開始,部署基于yangjianxin開發(fā)的流螢(Firefly)中文對話式大語言模型的http服務端

    Firefly(流螢) ?是yangjianxin開發(fā)的開源的中文大語言模型項目,本文主要實現將此模型部署到http服務器上,語言實現:python,本項目為雙創(chuàng)項目后端部分代碼(本人根據firefly訓練代碼修改+微調的模型暫不方便開源),樣例模型改用firefly1b4模型 項目環(huán)境: 1.pytorch:2.0.1+cpu 2.transfo

    2024年02月12日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包