在日常代码书写代码时可以借助C++关键字,简化C++代码书写,提高代码的安全性、效率和可读性。当前我常用关键字如下含有delete、default、nodiscard、const、constexpr、override和final。
其中override和final已在[关键字] override和final中做过叙述,在此不再赘述。
default
default是程序员显性地告诉编译器“你按你的方式为我生成这个函数吧”,由编译器生成合理的默认行为。通常用于由编译器生成类的6个默认函数中的部分和全部,注意生成的默认函数为浅拷贝。
示例代码:
class DefaultClass {
public:
// 默认构造函数
DefaultClass() = default;
// 析构函数
~DefaultClass() = default;
// 拷贝构造函数
DefaultClass(const DefaultClass&) = default;
// 拷贝赋值运算符
DefaultClass&operator=(const DefaultClass&) = default;
// 移动构造函数 (C++11 及更高版本)
DefaultClass(DefaultClass &&) = default;
// 移动赋值运算符 (C++11 及更高版本)
DefaultClass&operator=(DefaultClass &&) = default;
// ... 类的其他成员 ...
};
比如在虚基类中,析构函数生成为虚函数时,直接使用default关键字,不必书写其实现。
class IVideoProcess
{
public:
virtual ~IVideoProcess()=default;
virtual int DoProcess(constchar*data,intdata_length)=0;
};
delete
delete用于指定指定类的某些成员函数或运算符不能被使用。这对于防止不合理的操作或者强制执行某些设计决策非常有用。比如针对单例模式,其拷贝构造函数、拷贝赋值、移动构造函数、移动赋值应该被显示的禁止,避免出现未定义行为。
示例代码如下:
#pragmaonce
#include<iostream>
class Singleton
{
public:
static Singleton& getInstance() {
static Singleton single;
return single;
}
Singleton(const Singleton&) = delete;
Singleton&operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton&operator=(Singleton&&) = delete;
// 示例成员函数
void doSomething(){
std::cout << "Singleton is doing something..." << std::endl;
}
private:
Singleton() =default;
~Singleton() =default;
};
void test_single()
{
Singleton& s1 = Singleton::getInstance();
s1.doSomething();
// Singleton& s2 = Singleton(); // 编译错误:私有构造函数
// Singleton s3 = Singleton::getInstance(); // 编译错误:拷贝构造函数被删除
}
nodiscard
nodiscard作为C++17引入的关键字,用于指示函数的返回值不能被忽略,当函数的返回值被声明为[[nodiscard]]时,如果调用该函数时未使用其返回值,编译器将发出警告或错误。
这有助于减少无意中忽视重要返回值导致的错误。[[nodiscard]]不仅可以用于成员函数也可以用于普通函数。
示例代码:
//普通函数
[[nodiscard]] bool checkStatus(){
return isReady; // 假设这是检查某种状态的函数
}
class MyObject
{
public:
//成员函数
[[nodiscard]] bool checkState() {
return true; // 假设这是检查某种状态的函数
}
};
const
在文章历史上最全的const用法总结中讲解了const的部分用法,在此基础上补充,const不仅修饰函数传参,还可以修饰函数,还可以修饰函数返回值。
class People {
public:
People(std::stringnam, intage):m_name{nam},m_age{age}{}
[[nodiscard]] const int GetAge() const{
return m_age;
}
void SetAge(const int age){
m_age= age;
}
private:
int m_age{0};
std::string m_name{""};
};
constexpr
既然已经有了const为什么还要constexpr呢,const保证变量/函数的常量属性,可是constexpr尽可能的保证其常量属性且保证编译期可知。
#include<iostream>
// constexpr变量示例
constexpr int myConstVar = 42; // 编译时常量
// constexpr函数示例,返回编译时常量
constexpr int multiplyByTwo(int x) {
return x * 2;
}
// 另一个使用模板的constexpr函数示例
template<typename T>
constexpr T add(T a, T b) {
return a + b;
}
int test_keys() {
// 在编译时计算常量表达式的值
constexpr int result1 = multiplyByTwo(myConstVar); // 编译期结果已知,84
// 使用模板的constexpr函数
constexpr int result2 = add(3, 4); // 编译期结果已知,7
std::cout << "Result 2: " << result2 << std::endl;
// 注意:虽然multiplyByTwo和add是constexpr函数,但你也可以在运行时调用它们
int A= 10;
int runtimeResult1 = multiplyByTwo(A); // 结果为20
std::cout << "Runtime Result 1: " << runtimeResult1 << std::endl;
int c=5,d=6;
int runtimeResult2 = add(c, d); // 结果为11
std::cout << "Runtime Result 2: " << runtimeResult2 << std::endl;
return 0;
}
函数的编译后的汇编代码如下
总结
每个关键字都有其独特的用途,从控制类的行为到优化函数调用,再到确保代码的正确性和高效性。本文列出的主要是我常用的几个,欢迎大家评论区留言自己用的好用的关键字