还在用AI写论文被查AIGC?8款神器维普查重一把过!
2026/1/1 19:14:50
// 非泛型实现:需要重复编写 void swap_int(int& a, int& b) { int temp = a; a = b; b = temp; } void swap_double(double& a, double& b) { double temp = a; a = b; b = temp; } // 泛型实现:一次定义,处处使用 template<typename T> void swap(T& a, T& b) { T temp = a; a = b; b = temp; }上述模板函数在编译期根据调用上下文自动推导类型,生成对应版本,消除冗余代码。| 组件 | 作用 | 典型示例 |
|---|---|---|
| 容器 | 存储数据 | vector, list, map |
| 迭代器 | 统一访问方式 | begin(), end() |
| 算法 | 操作数据 | sort, find, copy |
auto value = 42; // 推导为 int auto iter = vec.begin(); // 推导为 std::vector<int>::iterator上述代码中,`auto`根据初始化表达式自动确定变量类型,尤其在迭代器和Lambda表达式中优势明显。int x = 5; decltype(x) y = 10; // y 的类型为 int decltype(x + y) z = x + y; // z 的类型为 int与`auto`不同,`decltype`严格遵循表达式的类型规则,包括引用和const限定符。std::enable_if结合SFINAE,可实现对模板参数的精细控制:template<typename T> typename std::enable_if<std::is_integral<T>::value, void>::type process(T value) { // 仅当T为整型时参与重载 }上述代码通过std::is_integral<T>::value判断类型是否为整型,若不满足则触发SFINAE,避免编译错误。&&声明,允许绑定临时对象,避免不必要的拷贝。它为移动语义提供了语言层面的支持。std::move和右值引用可实现资源的高效转移:template<typename T> void push_back(T&& value) { data.push_back(std::forward<T>(value)); // 完美转发 }上述代码利用完美转发保留参数的左/右值属性,若传入临时对象,则触发移动构造而非拷贝,显著提升容器插入效率。std::function是一种通用、多态的函数封装器,能够统一处理函数指针、lambda 表达式、绑定对象等可调用类型。其核心优势在于类型安全的抽象,避免了传统函数指针的类型不匹配问题。
#include <functional> #include <iostream> void print(int x) { std::cout << x << std::endl; } int main() { std::function<void(int)> func = print; func(42); // 安全调用 }上述代码中,func明确限定接受一个int参数且无返回值的函数,任何类型不匹配的赋值将在编译期被拒绝,确保类型一致性。
std::bind允许将参数部分绑定到函数,生成新的可调用对象,并与std::function无缝集成,提升回调灵活性。
_1)实现延迟求值template<typename T> void print(T value) { std::cout << value << std::endl; } template<typename T, typename... Args> void print(T first, Args... args) { std::cout << first << " "; print(args...); // 递归展开 }上述代码通过特化单参数版本作为递归终点,多参数时依次解包并传递剩余参数,实现类型安全的展开。auto transform = <T, U>(vector<T> v, function<U(T)> f) -> vector<U> { vector<U> result; for (auto& item : v) result.push_back(f(item)); return result; };上述代码定义了一个泛型 Lambda,接受任意类型容器和映射函数。T 为输入元素类型,U 为输出元素类型,实现灵活的数据转换。constexpr函数支持更复杂的逻辑,结合函数模板可实现泛型编译期计算。通过类型参数推导,同一函数可处理多种字面量类型。template <typename T> constexpr T power(T base, int exp) { T result = 1; for (int i = 0; i < exp; ++i) result *= base; return result; }上述代码在编译期计算幂运算。参数base和exp若为常量表达式,结果将在编译阶段完成求值,提升运行时性能。template <typename T> auto process(T value) { if constexpr (std::is_integral_v<T>) { return value * 2; // 整型:乘以2 } else if constexpr (std::is_floating_point_v<T>) { return value + 1.0; // 浮点型:加1.0 } else { static_assert(false_v<T>, "Unsupported type"); } }上述代码中,`if constexpr` 根据 `T` 的类型在编译期决定执行路径。例如,传入 `int` 时仅实例化第一个分支,浮点分支不会被生成,避免类型不匹配错误。std::map<std::string, int> config = {{"timeout", 5000}, {"retries", 3}}; for (const auto& [key, value] : config) { std::cout << key << ": " << value << "\n"; }上述代码中,const auto&避免了不必要的拷贝,且保证了解绑变量在迭代期间始终有效。若原容器为临时对象,则需通过值捕获或延长生命周期来防止内存错误。auto推导类型,减少类型不匹配风险if constexpr对不同结构体成员做编译期校验template <typename T> std::optional<T> safe_divide(T a, T b) { if (b == 0) return std::nullopt; return a / b; }该函数通过返回 `std::optional` 明确表达“可能无结果”的语义。调用方必须显式检查是否存在值,避免隐式错误传播。`std::nullopt` 表示空状态,替代了返回指针的 `nullptr` 惯用法。std::variant提供了一种类型安全的联合体替代方案,避免了传统union因缺乏析构信息而导致的资源管理问题。std::variant<int, std::string, double> v = "hello";该定义表示变量v可在三种指定类型中选择其一存储。编译器确保任何时候仅有一种类型处于活动状态,且自动调用对应构造与析构函数。std::get<T>(v)或std::visit可安全访问内容:std::get<std::string>(v):若当前非字符串类型将抛出异常std::visit(visitor, v):通过函数对象统一处理所有可能类型std::variant具有更优的内存局部性与性能表现,适用于标签联合(tagged union)场景。template struct Box { T value; Box(T v) : value(v) {} }; Box b{3.14f}; // 推导为 Box,若期望 double 则出错上述代码中,float 字面量被推导为float,若后续计算需double精度则产生隐患。Box<double> b{3.14};explicit#include <concepts> template<std::integral T> T add(T a, T b) { return a + b; }该函数在调用时若传入浮点数或自定义非整型类,将立即触发清晰的编译错误,而非陷入冗长的模板展开堆栈。std::random_access_iterator概念std::is_arithmetic_v)| 类型成员 | 访问模式 | 泛型约束 |
|---|---|---|
| user_id | 只读 | Integral && Positive |
| 读写 | String && ValidFormat |