1. move语义 and right 值引用
1.1 right 值引用
right 值引用 is C++11引入 new features, using&&符号表示, 用于引用临时object ( right 值) :
#include <iostream>
#include <string>
using namespace std;
void printValue(int& lvalue) { // left 值引用parameter
cout << " left 值引用: " << lvalue << endl;
}
void printValue(int&& rvalue) { // right 值引用parameter
cout << " right 值引用: " << rvalue << endl;
}
int main() {
int x = 10; // x is left 值
printValue(x); // 调用 left 值引用version
printValue(20); // 调用 right 值引用version
printValue(x + 5); // 调用 right 值引用version
return 0;
}
1.2 moveconstructfunction and move赋值运算符
moveconstructfunction and move赋值运算符用于将resource from 一个object转移 to 另一个object, 避免不必要 copy:
#include <iostream>
#include <string>
using namespace std;
class MyString {
private:
char* data;
size_t length;
public:
// constructfunction
MyString(const char* str) {
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
cout << "constructfunction: " << data << endl;
}
// 析构function
~MyString() {
if (data) {
cout << "析构function: " << data << endl;
delete[] data;
}
}
// 拷贝constructfunction
MyString(const MyString& other) {
length = other.length;
data = new char[length + 1];
strcpy(data, other.data);
cout << "拷贝constructfunction: " << data << endl;
}
// moveconstructfunction
MyString(MyString&& other) noexcept {
length = other.length;
data = other.data; // 直接接管resource
other.data = nullptr; // 防止原object析构时释放resource
cout << "moveconstructfunction: " << data << endl;
}
// 拷贝赋值运算符
MyString& operator=(const MyString& other) {
if (this != &other) {
delete[] data;
length = other.length;
data = new char[length + 1];
strcpy(data, other.data);
cout << "拷贝赋值运算符: " << data << endl;
}
return *this;
}
// move赋值运算符
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data;
length = other.length;
data = other.data; // 直接接管resource
other.data = nullptr; // 防止原object析构时释放resource
cout << "move赋值运算符: " << data << endl;
}
return *this;
}
const char* c_str() const {
return data;
}
};
MyString createString() {
return MyString("Hello, World!"); // 返回临时object
}
int main() {
cout << "=== creations1 ===" << endl;
MyString s1("Hello");
cout << "\n=== 拷贝constructs2 ===" << endl;
MyString s2 = s1; // 调用拷贝constructfunction
cout << "\n=== moveconstructs3 ===" << endl;
MyString s3 = createString(); // 调用moveconstructfunction
cout << "\n=== move赋值s4 ===" << endl;
MyString s4("Initial");
s4 = createString(); // 调用move赋值运算符
cout << "\n=== 程序结束 ===" << endl;
return 0;
}
1.3 std::movefunction
std::movefunction用于将 left 值转换 for right 值引用, from 而可以调用moveconstructfunction or move赋值运算符:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "Hello, World!";
cout << "s1: " << s1 << endl;
// usingstd::move将s1转换 for right 值引用
string s2 = move(s1);
cout << "s2: " << s2 << endl;
cout << "s1: " << s1 << endl; // s1现 in for 空
return 0;
}
2. Lambda表达式深入
2.1 Lambda表达式 语法
Lambda表达式 basic语法:
[捕获list](parameterlist) mutable -> 返回class型 { function体 }
2.1.1 捕获list
[]: 不捕获任何variable[=]: 以值方式捕获所 has out 部variable[&]: 以引用方式捕获所 has out 部variable[x]: 以值方式捕获x[&x]: 以引用方式捕获x[=, &x]: 以值方式捕获所 has out 部variable, 以引用方式捕获x[this]: 捕获当 before object this指针
2.1.2 Lambda表达式 using
#include <iostream>
#include <vector>
#include <algorithms>
using namespace std;
int main() {
vector numbers = {5, 2, 8, 1, 9, 3};
// usinglambda表达式sort
sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b; // 降序sort
});
// usinglambda表达式遍历
for_each(numbers.begin(), numbers.end(), [](int n) {
cout << n << " ";
});
cout << endl;
// 捕获 out 部variable
int threshold = 5;
vector filtered;
copy_if(numbers.begin(), numbers.end(), back_inserter(filtered),
[threshold](int n) {
return n > threshold;
});
cout << " big 于" << threshold << " 数: ";
for (int n : filtered) {
cout << n << " ";
}
cout << endl;
return 0;
}
2.2 Lambda表达式 class型
Lambda表达式 class型 is 编译器生成 匿名class型, 它可以转换 for function指针 or store in std::functionin:
#include <iostream>
#include <functional>
using namespace std;
int main() {
// storelambda表达式 to std::function
function add = [](int a, int b) {
return a + b;
};
cout << "3 + 5 = " << add(3, 5) << endl;
// serving asreturn value
auto createMultiplier(int factor) {
return [factor](int x) {
return x * factor;
};
}
auto multiplyBy2 = createMultiplier(2);
cout << "5 * 2 = " << multiplyBy2(5) << endl;
return 0;
}
3. 智能指针进阶
3.1 std::make_unique and std::make_shared
C++14引入了std::make_unique and std::make_sharedfunction, 用于security地creation智能指针:
#include <iostream>
#include <memory>
using namespace std;
class Person {
private:
string name;
public:
Person(const string& n) : name(n) {
cout << "Personconstructfunction: " << name << endl;
}
~Person() {
cout << "Person析构function: " << name << endl;
}
void sayHello() {
cout << "Hello, I'm " << name << endl;
}
};
int main() {
// usingmake_uniquecreationunique_ptr
unique_ptr p1 = make_unique("张三");
p1->sayHello();
// usingmake_sharedcreationshared_ptr
shared_ptr p2 = make_shared("李四");
p2->sayHello();
return 0;
}
3.2 自定义delete器
可以 for 智能指针指定自定义delete器, 用于特殊 resourcemanagement:
#include <iostream>
#include <memory>
using namespace std;
// 自定义delete器
void customDeleter(int* p) {
cout << "自定义delete器: 释放memory" << endl;
delete p;
}
int main() {
// usingfunctionserving asdelete器
unique_ptr p1(new int(10), customDeleter);
cout << "p1 值: " << *p1 << endl;
// usinglambda表达式serving asdelete器
auto deleter = [](int* p) {
cout << "Lambdadelete器: 释放memory" << endl;
delete p;
};
unique_ptr p2(new int(20), deleter);
cout << "p2 值: " << *p2 << endl;
return 0;
}
4. constexpr and 编译期计算
4.1 constexprvariable
constexpr关键字用于声明 in 编译期计算 常量:
#include <iostream>
using namespace std;
int main() {
constexpr int maxSize = 100;
int arr[maxSize]; // 编译期确定 big small
constexpr double pi = 3.14159;
constexpr double radius = 5.0;
constexpr double area = pi * radius * radius;
cout << "圆 面积: " << area << endl;
return 0;
}
4.2 constexprfunction
constexprfunction可以 in 编译期计算其return value:
#include <iostream>
using namespace std;
// constexprfunction
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
// 编译期计算
constexpr int fact5 = factorial(5);
cout << "5! = " << fact5 << endl;
// run期计算
int n;
cout << "输入一个数: ";
cin >> n;
int factN = factorial(n);
cout << n << "! = " << factN << endl;
return 0;
}
5. C++11/14/17/20 new features
5.1 范围-based for循环
C++11引入了范围-based for循环, 简化了containers 遍历:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector fruits = {"苹果", "香蕉", "橙子", "葡萄"};
// 范围-based for循环
for (const auto& fruit : fruits) {
cout << fruit << " ";
}
cout << endl;
// modify元素
vector numbers = {1, 2, 3, 4, 5};
for (auto& num : numbers) {
num *= 2;
}
for (const auto& num : numbers) {
cout << num << " ";
}
cout << endl;
return 0;
}
5.2 强class型枚举
C++11引入了强class型枚举, 避免了传统枚举 作用域issues:
#include <iostream>
using namespace std;
// 传统枚举
enum Color {
RED, GREEN, BLUE
};
// 强class型枚举
enum class Fruit {
APPLE, BANANA, ORANGE
};
enum class Vehicle {
CAR, BUS, TRUCK
};
int main() {
// 传统枚举
Color c = RED;
cout << "传统枚举值: " << c << endl;
// 强class型枚举
Fruit f = Fruit::APPLE;
Vehicle v = Vehicle::CAR;
// 强class型枚举需要显式转换 for 整型
cout << "强class型枚举值: " << static_cast(f) << endl;
cout << "强class型枚举值: " << static_cast(v) << endl;
return 0;
}
5.3 override and final关键字
C++11引入了override and final关键字, 用于明确虚function 覆盖 and 防止inheritance:
#include <iostream>
using namespace std;
class Base {
public:
virtual void foo() {
cout << "Base::foo()" << endl;
}
// 防止forkclass覆盖此function
virtual void bar() final {
cout << "Base::bar()" << endl;
}
};
class Derived : public Base {
public:
// 明确表示覆盖基class 虚function
void foo() override {
cout << "Derived::foo()" << endl;
}
// error: 不能覆盖finalfunction
// void bar() override {
// cout << "Derived::bar()" << endl;
// }
};
// 防止被inheritance
class FinalClass final {
public:
void func() {
cout << "FinalClass::func()" << endl;
}
};
// error: 不能inheritancefinalclass
// class DerivedFromFinal : public FinalClass {
// };
int main() {
Base* b = new Derived();
b->foo();
b->bar();
delete b;
return 0;
}
5.4 structure化绑定 (C++17)
C++17引入了structure化绑定, 用于同时声明 many 个variable并 from 复合class型in提取值:
#include <iostream>
#include <tuple>
#include <map>
using namespace std;
int main() {
// from tuplein提取值
auto person = make_tuple("张三", 25, 85.5);
auto [name, age, score] = person;
cout << "姓名: " << name << ", 年龄: " << age << ", 分数: " << score << endl;
// from pairin提取值
pair product = {"苹果", 5};
auto [productName, price] = product;
cout << "商品: " << productName << ", 价格: " << price << endl;
// from mapin提取值
map scores = {
{"张三", 95},
{"李四", 88},
{"王五", 92}
};
for (const auto& [student, score] : scores) {
cout << student << ": " << score << endl;
}
return 0;
}
5.5 fold表达式 (C++17)
C++17引入了fold表达式, 用于简化可变parameter模板 implementation:
#include <iostream> using namespace std; // fold表达式implementation求 and templateauto sum(Args... args) { return (args + ...); } // fold表达式implementation打印 template void print(Args... args) { (cout << ... << args) << endl; } int main() { cout << "sum(1, 2, 3, 4, 5) = " << sum(1, 2, 3, 4, 5) << endl; print("Hello", " ", "World", "!"); return 0; }
实践case: implementation一个threadsecurity singleton pattern
writing一个C++程序, using现代C++featuresimplementation一个threadsecurity singleton pattern.
requirementsanalysis
- implementation一个单例class, 确保全局只 has 一个instance.
- 保证threadsecurity, many threadenvironment under 也能正确工作.
- using现代C++features, such as智能指针, lambda表达式etc..
- providing获取instance 静态method.
referencecode
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
using namespace std;
class Singleton {
private:
string data;
// 私 has constructfunction
Singleton(const string& d) : data(d) {
cout << "Singletonconstructfunction" << endl;
}
// 私 has 析构function
~Singleton() {
cout << "Singleton析构function" << endl;
}
public:
// 禁止拷贝 and move
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
// 获取instance 静态method
static Singleton& getInstance(const string& data = "默认值") {
// 局部静态variableimplementation单例 (C++11 after threadsecurity)
static Singleton instance(data);
return instance;
}
// 业务method
void setData(const string& d) {
data = d;
}
string getData() const {
return data;
}
void showMessage() {
cout << "Singletondata: " << data << endl;
}
};
// testfunction
void testSingleton(int id) {
cout << "thread" << id << "开始" << endl;
// 获取单例instance
Singleton& s = Singleton::getInstance("thread" + to_string(id) + " data");
s.showMessage();
// modifydata
s.setData("thread" + to_string(id) + "modify after data");
s.showMessage();
cout << "thread" << id << "结束" << endl;
}
int main() {
cout << "主thread开始" << endl;
// 主thread获取instance
Singleton& s = Singleton::getInstance("主threaddata");
s.showMessage();
// creation many 个threadtest
thread t1(testSingleton, 1);
thread t2(testSingleton, 2);
thread t3(testSingleton, 3);
// etc.待thread结束
t1.join();
t2.join();
t3.join();
// 主thread再次获取instance
cout << "\n主thread再次获取instance" << endl;
Singleton& s2 = Singleton::getInstance();
s2.showMessage();
cout << "主thread结束" << endl;
return 0;
}
run结果
主thread开始 Singletonconstructfunction Singletondata: 主threaddata thread1开始 Singletondata: 主threaddata Singletondata: thread1modify after data thread1结束 thread2开始 Singletondata: thread1modify after data Singletondata: thread2modify after data thread2结束 thread3开始 Singletondata: thread2modify after data Singletondata: thread3modify after data thread3结束 主thread再次获取instance Singletondata: thread3modify after data 主thread结束 Singleton析构function
互动练习
练习1: writing一个C++程序, usingmove语义 and right 值引用implementation一个 high 效 stringclass, supportmoveconstruct and move赋值.
练习2: writing一个C++程序, usinglambda表达式 and STLalgorithmsimplementation以 under functions:
- filter出 vector in big 于 10 元素
- 将filter after 元素乘以 2
- 计算processing after 元素 总 and
练习3: writing一个C++程序, using constexpr implementation编译期计算斐波那契数列 第 n 项.
练习4: writing一个C++程序, usingstructure化绑定 (C++17) 遍历一个 map, 并打印出所 has 键值 for .