39、Cpp常用新特性
大约 4 分钟C++C++基础编程程序厨
C++现在基本是每三年引入一些新特性,C++11、C++14、C++17和C++20引入了许多进阶特性,极大地提升了C++的灵活性和开发效率。
本文会详细介绍主要的新特性。
右值引用与移动语义
右值引用的概念
右值引用是C++11引入的一种引用类型,用于绑定临时对象(右值)。右值引用的语法为T&&
。
移动语义
移动语义是指将资源(如内存)从一个对象转移到另一个对象,而不是复制资源。
合理使用移动语义,可以避免不必要的复制操作,提高性能。
代码示例
#include <iostream>
#include <vector>
class MyClass {
public:
MyClass() { std::cout << "MyClass constructed." << std::endl; }
~MyClass() { std::cout << "MyClass destroyed." << std::endl; }
// 移动构造函数
MyClass(MyClass&& other) noexcept {
std::cout << "MyClass moved." << std::endl;
}
// 移动赋值运算符
MyClass& operator=(MyClass&& other) noexcept {
std::cout << "MyClass move-assigned." << std::endl;
return *this;
}
};
int main() {
MyClass obj1;
MyClass obj2 = std::move(obj1); // 调用移动构造函数
MyClass obj3;
obj3 = std::move(obj2); // 调用移动赋值运算符
return 0;
}
std::move
std::move
用于将对象转换为右值引用,从而触发移动语义。
代码示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = std::move(vec1); // 使用std::move触发移动语义
std::cout << "vec1 size: " << vec1.size() << std::endl; // 输出:0
std::cout << "vec2 size: " << vec2.size() << std::endl; // 输出:3
return 0;
}
完美转发与std::forward
完美转发的概念
完美转发是指在函数模板中将参数以**原始类型(左值或右值)**转发给另一个函数。
std::forward
std::forward
用于在函数模板中实现完美转发。
代码示例
#include <iostream>
void func(int& x) {
std::cout << "Lvalue reference: " << x << std::endl;
}
void func(int&& x) {
std::cout << "Rvalue reference: " << x << std::endl;
}
template <typename T>
void wrapper(T&& arg) {
func(std::forward<T>(arg)); // 使用std::forward实现完美转发
}
int main() {
int x = 10;
wrapper(x); // 调用func(int&)
wrapper(20); // 调用func(int&&)
return 0;
}
并发编程
std::thread
std::thread
是C++11引入的线程类,用于创建和管理线程。
代码示例
#include <iostream>
#include <thread>
void threadFunc() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(threadFunc); // 创建线程
t.join(); // 等待线程结束
return 0;
}
std::mutex
std::mutex
是C++11引入的互斥量类,用于保护共享资源。
代码示例
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void threadFunc(int id) {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
std::cout << "Thread " << id << " is running." << std::endl;
}
int main() {
std::thread t1(threadFunc, 1);
std::thread t2(threadFunc, 2);
t1.join();
t2.join();
return 0;
}
std::future与std::async
std::future
和std::async
用于异步任务和获取结果。
代码示例
#include <iostream>
#include <future>
int asyncFunc() {
return 42;
}
int main() {
std::future<int> fut = std::async(asyncFunc); // 启动异步任务
int result = fut.get(); // 获取结果
std::cout << "Result: " << result << std::endl; // 输出:42
return 0;
}
新增的数据类型与语法特性
std::optional(C++17)
std::optional
用于表示可能不存在的值,我经常使用。
代码示例
#include <iostream>
#include <optional>
std::optional<int> divide(int a, int b) {
if (b == 0) {
return std::nullopt; // 表示无值
}
return a / b;
}
int main() {
auto result = divide(10, 2);
if (result) {
std::cout << "Result: " << *result << std::endl; // 输出:5
} else {
std::cout << "Division by zero!" << std::endl;
}
return 0;
}
std::variant(C++17)
std::variant
用于表示多种类型的值。
代码示例
#include <iostream>
#include <variant>
#include <string>
int main() {
std::variant<int, double, std::string> v = 3.14;
if (std::holds_alternative<double>(v)) {
std::cout << "Double value: " << std::get<double>(v) << std::endl; // 输出:3.14
}
return 0;
}
结构化绑定(C++17)
结构化绑定用于将结构体或元组的成员绑定到变量。
代码示例
#include <iostream>
#include <tuple>
#include <string>
int main() {
std::tuple<int, double, std::string> t = {1, 3.14, "Hello"};
auto [x, y, z] = t; // 结构化绑定
std::cout << "x = " << x << ", y = " << y << ", z = " << z << std::endl; // 输出:x = 1, y = 3.14, z = Hello
return 0;
}
if与switch的初始化语句(C++17)
C++17允许在if
和switch
语句中定义变量。
代码示例
#include <iostream>
int main() {
if (int x = 10; x > 5) {
std::cout << "x is greater than 5: " << x << std::endl; // 输出:x is greater than 5: 10
}
return 0;
}
练习
- 使用移动语义实现一个简单的字符串类。
- 使用
std::thread
和std::mutex
实现一个多线程计数器。 - 使用
std::optional
实现一个安全的除法函数。 - 使用
std::variant
实现一个简单的类型安全的联合体。
