作者:求一個demo
版權聲明:著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處
內容通俗易懂,沒有廢話,文章最后是面試常問內容(建議通過標題目錄學習)
廢話不多說,我們直接開始------>>>>>>
一、const關鍵字
? ? ? ? 1、特點:
? ? ? ? ①用于定義常量,表示不可修改的值。
? ? ? ? ②可以應用于變量、函數參數、函數返回值、成員函數等。mutable修飾的成員變量可以在const成員函數中被修改。
class MyClass {
private:mutable int value;
public:void modifyValue() const {value = 10; // 正確:可以在 const 成員函數中修改 mutable 成員變量}
};
? ? ? ? ③提高代碼安全性和可讀性。
? ? ? ? 2、示例:
// 1. const變量
const int MAX_SIZE = 100;
// MAX_SIZE = 200; // 錯誤:不能修改const變量// 2. const指針
int value = 10;
const int* ptr1 = &value; // 指向const int的指針
// *ptr1 = 20; // 錯誤:不能通過ptr1修改值
ptr1 = nullptr; // 可以修改指針本身int* const ptr2 = &value; // const指針,指向int
*ptr2 = 20; // 可以修改指向的值
// ptr2 = nullptr; // 錯誤:不能修改指針本身// 3. const成員函數
class MyClass {
public:int getValue() const { // const成員函數,承諾不修改對象狀態return value;// value = 10; // 錯誤:不能在const成員函數中修改成員變量}
private:int value = 0;
};
二、引用
? ? ? ? 1、特點:
? ? ? ? ①引用是給變量取個別名,必須初始化,且不能重新綁定。
? ? ? ? ②沒有獨立的內存空間,與被引用變量共享同一內存。
? ? ? ? ③比指針更安全,不能為null。
? ? ? ? ④常用于函數參數傳遞和返回值。
? ? ? ? 2、示例:
int main() {int x = 10;int& ref = x; // ref是x的引用ref = 20; // 修改ref等同于修改xstd::cout << x; // 輸出20int y = 30;// ref = y; // 不是重新綁定,而是把y的值賦給ref(即x)// 引用作為函數參數auto swap = [](int& a, int& b) {int temp = a;a = b;b = temp;};int a = 1, b = 2;swap(a, b); // 直接修改原變量std::cout << a << " " << b; // 輸出2 1
}
三、const引用
? ? ? ? 1、特點:
? ? ? ? ①不能通過引用修改被引用的對象。
int num = 10;
const int& ref = num;
ref = 20; // 錯誤,不能通過const引用修改被引用的對象
num = 20; // 正確,直接通過變量名可以修改
? ? ? ? ②可以綁定到臨時對象、右值。
const int& ref1 = 5; // 合法,將const引用綁定到字面量5
const int& ref2 = int(10); // 合法,將const引用綁定到臨時對象
int num = 10;
int& ref3 = num; // 合法
int& ref4 = 5; // 錯誤,普通引用不能綁定到右值
? ? ? ? ③常用于函數參數,避免不必要的拷貝同時防止修改。(下面第二條進行了詳細解釋)
#include <iostream>
#include <string>
using namespace std;void printString(const string& str) {cout << str << endl;
}
int main() {string s = "Hello, World!";printString(s);return 0;
}
? ? ? ? 2、注意:普通函數使用引用傳遞是為了避免對象拷貝,而拷貝構造函數使用引用傳遞是為了接收要被拷貝的對象,并且在函數體內部完成對象的拷貝操作。
#include <iostream>
using namespace std;class MyClass {
public:int* data;// 構造函數MyClass(int value) {data = new int(value);cout << "Constructor called." << endl;}// 拷貝構造函數MyClass(const MyClass& other) {data = new int(*(other.data));cout << "Copy constructor called." << endl;}// 析構函數~MyClass() {delete data;}
};// 使用const引用作為參數的普通函數
void func(const MyClass& obj) {// 函數內部操作cout << "Value in func: " << *(obj.data) << endl;
}int main() {MyClass obj(10);func(obj);return 0;
}
四、const、引用以及const引用的比較
? ? ? ? ①能否修改:const變量不能修改;引用可以修改,const 引用不能修改。
? ? ? ? ②能否重新綁定:const變量無綁定這一說;引用不能重新綁定;const引用不能重新綁定。
? ? ? ? ③是否需要初始化:const變量必須初始化;引用必須初始化;const引用必須初始化。
? ? ? ? ④能否綁定到臨時對象:const變量無綁定這一說;引用不能綁定;const引用能綁定到臨時對象。
? ? ? ? ⑤內存占用:const變量有獨立內存;引用無獨立內存;const引用無獨立內存。
? ? ? ? ⑥主要用途:const變量用來定義常量;引用用來取別名、參數傳遞;const引用安全傳遞參數。
五、綜合應用
????????示例:
#include <iostream>
#include <string>
using namespace std;class Student {
public:// const引用參數,避免拷貝同時防止修改Student(const string& name) : name(name) {}// const成員函數,承諾不修改對象狀態const string& getName() const { return name; }// 返回const引用,避免拷貝同時防止外部修改const string& getConstRefName() const { return name; }// 返回普通引用,允許外部修改string& getRefName() { return name; }private:string name;
};void printStudent(const Student& s) {cout << "Student: " << s.getName() << "\n";// s.getRefName() = "NewName"; // 錯誤:s是const引用
}int main() {const string name = "Alice";Student s(name);printStudent(s);// 通過引用修改s.getRefName() = "Bob";printStudent(s);// 嘗試通過const引用修改const string& nameRef = s.getConstRefName();// nameRef = "Charlie"; // 錯誤:不能通過const引用修改// 臨時對象printStudent(Student("Temp"));
}
六、constexpr與const區別
? ? ? ? 1、constexpr
? ? ? ? (1)介紹:constexpr是C++11新特性,用于定義編譯器常量和能在編譯期求值的函數。
? ? ? ? (2)特點:
? ? ? ? ? ? ? ? ①表示值或函數在編譯期就能確定。
? ? ? ? ? ? ? ? ②可用于變量、函數、構造函數等。
? ? ? ? ? ? ? ? ③C++17引入了if constexpr編譯期條件判斷。
? ? ? ? (3)用途:
? ? ? ? ? ? ? ? ①在編譯期完成計算,而不是在運行期
constexpr int factorial(int n) {return (n <= 1) ? 1 : n * factorial(n - 1);
}constexpr int fact5 = factorial(5); // 編譯時計算120
// 等價于直接寫 constexpr int fact5 = 120;
? ? ? ? ? ? ? ? ②比#define宏更加安全。
constexpr int MAX_SIZE = 100; // 替代 #define MAX_SIZE 100
int buffer[MAX_SIZE]; // 可用于數組大小
? ? ? ? ? ? ? ? ③可以在編譯期構造和初始化對象
class Point {
public:constexpr Point(double x, double y) : x(x), y(y) {}constexpr double getX() const { return x; }
private:double x, y;
};constexpr Point origin(0.0, 0.0); // 編譯期構造
constexpr double x = origin.getX(); // 編譯期調用成員函數
? ? ? ? (4)示例:
constexpr int size = 10; // 編譯期常量
int arr[size]; // 可用于數組大小// constexpr函數
constexpr int factorial(int n) {return n <= 1 ? 1 : n * factorial(n - 1);
}constexpr int fact5 = factorial(5); // 編譯期計算
? ? ? ? 2、constexpr和const區別
? ? ? ? ①求值時機:const運行時常量(也可以是編譯期確定);constexpr必須是編譯期確定。
? ? ? ? ②初始化要求:const必須初始化;constexpr必須用常量表達式初始化,可以定義數組、結構體。
? ? ? ? ③函數應用:const不能保證編譯期求值;constexpr可以在編譯期求值。
? ? ? ? ④指針使用:const可以修飾指針本身或指向的內容;constexpr必須指向編譯期確定的內存。
? ? ? ? ⑤主要用途:const運行時常量,保證不變性,不能作為模板參數;constexpr編譯期計算,可以作為模板參數。
#include <iostream>
using namespace std;int main()
{constexpr int num = 1 + 2 + 3;//constexpr也可換成const,這樣下面url[num]也不報錯int url[num] = {1,2,3,4,5,6};//如果上面不寫constexpr,直接url[num],則會顯示num不可用做常量couts<< url[1] << endl;return 0;
}
七、校招面試常問內容
1、const的作用的用法?
????????①定義常量:const int MAX = 100。
? ? ? ? ②保護函數參數不被修改:void func(const int other)。
? ? ? ? ③保護類成員不被修改:const成員函數。
? ? ? ? ④保護指針指向的內容:const char* p或char* const p。
2、const指針與指針const的區別?
const int* p1; // 指向const int的指針,指針可變,內容不可變
int const* p2; // 同上,等價寫法
int* const p3; // const指針,指向int,指針不可變,內容可變
const int* const p4; // 指向const int的const指針,都不可變
3、const成員函數的作用是什么?能修改成員變量嗎?
? ? ? ? ①不修改對象狀態。
? ? ? ? ②不能修改非mutable成員變量。
? ? ? ? ③可以被const對象調用。
4、指針和引用的區別?
5、為什么函數參數常用const引用?
? ? ? ? ①避免拷貝大對象的開銷。
? ? ? ? ②防止意外修改傳入的參數。
? ? ? ? ③可以接受臨時對象(右值)。
6、函數返回引用時,需要注意什么?
? ? ? ? ①絕不能返回局部變量的引用(局部變量在函數內部定義,函數結束空間后內存空間被釋放。如果返回局部變量的引用,在函數外使用該引用,訪問的是不存在的內存空間)。
? ? ? ? ②可以返回成員變量、靜態變量或傳入參數的引用(成員變量是類的一部分,靜態變量在整個程序運行期間都存在,傳入參數的生命周期在函數調用期間都有效)。
7、const引用的特點?
? ? ? ? ①可以綁定到右值(臨時對象)。
? ? ? ? ②可以延長對象的生命周期。
最后,如有不足和錯誤的地方,期待私信指正!