作者:求一个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等同于修改x
std::cout << x; // 输出20
int 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引用的特点?
①可以绑定到右值(临时对象)。
②可以延长对象的生命周期。
最后,如有不足和错误的地方,期待私信指正!