stl std::forward

本文深入探讨了C++中如何通过模板实现参数转发,并详细解释了std::forward的工作原理及其实现细节。通过具体示例,展示了如何利用模板使函数能够透明地处理各种类型的参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作用:

用于模板的代理函数中参数转发,而能够保持参数的实际类型


例子:

#include <iostream>
#include <functional>

void add(int& a, int&& b, int c, int *d) {
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
    std::cout << *d << std::endl;
}

void add_proxy(int &a, int &&b, int c, int *d) {
    add(a, std::move(b), c, d);
}

template<typename fun, typename A, typename B, typename C, typename D>
void proxy_template(fun f, A&& a, B&& b, C&& c, D&& d) {
    f(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d));
}

int main() {
    int a = 1;
    add_proxy(a, 2, 3, &a);
    proxy_template(add, a, 2, 3, &a);
    return 0;
}
add_proxy为明确类型的手动代理调用

proxy_template为模版类型的4参数方法代理调用,其无论你传递的参数为什么类型,均可以按照其实际的类型进行转发


std::forward源码:

  template<typename _Tp>
    constexpr _Tp&&
    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
    { return static_cast<_Tp&&>(__t); }
只列了一种forward情况,另一种为::type&& __t,这种为传递给forward为右值的情况,这里暂时用不上

说明:

A&& a,传递实参int a,推导模板参数a为int& && a(引用折叠)->int& a, 所以A=int&,a=int&

std::forward<A>(a)->std::forward<int&>(int&), std::remove_reference<int&>::type->int,所以匹配上面的std::forward源码,

std::remove_reference<int&>::type&->int&

所以最终代码为:

constexpr int& &&forward(std::remove_reference<int&>::type& __t) noexcept {return static_cast<int& &&>(__t):}

constexpr int& forward(std::remove_reference<int&>::type& __t) noexcept {return static_cast<int&>(__t);}

传递给模板的是左值,那么传递下去的还是左值


B&& b,传递3,推导模版参数b为int&& b, 所以B=int,b=int&&

std::forward<B>(b)->std::forward<int>(int&)(虽然b=int&&,虽然称为右值引用,但是只是表明他是一种有能力访问临时变量的引用,后续使用的时候,其本身是作为左值使用),

std::remove_reference<int>::type->int,所以匹配上面的std::forward源码,

std::remove_reference<int>::type&->int&

最终代码为:

constexpr int&& forward(std::remove_reference<int>::type& __t) noexcept { return static_cast<int&&>(__t);}

即传递给模板的是右值,那么传递下去的还是右值


C和B一致


D实际传递为int*,如果把int*整个当作一个左值来看,那么其与A是一致的


### C++ std::forward_list 使用指南和常见问题 #### 1. 简介 `std::forward_list` 是 C++ 标准模板库(STL)中的一种单向链表容器,它只支持从头部插入元素,并且不提供随机访问功能。与 `std::list` 不同,`std::forward_list` 只维护一个指向下一个节点的指针,因此它的内存开销较小[^2]。 #### 2. 基本特性 - **单向链表**:`std::forward_list` 的每个节点仅包含一个指向下一个节点的指针,这使得它在某些场景下比 `std::list` 更节省内存。 - **无尾指针**:`std::forward_list` 不维护尾指针,因此无法在常数时间内访问最后一个元素。 - **高效头部插入**:在头部插入元素的操作非常高效,时间复杂度为 O(1)。 #### 3. 构造函数 `std::forward_list` 提供了多种构造方式,包括默认构造、指定大小构造、使用初始化列表构造以及通过迭代器范围构造等[^4]。 ```cpp #include <iostream> #include <forward_list> int main() { // 创建一个空的 forward_list std::forward_list<int> fl1; // 使用初始化列表构造 forward_list std::forward_list<int> fl2{1, 2, 3, 4, 5}; // 通过迭代器范围构造 forward_list std::forward_list<int> fl3(fl2.begin(), fl2.end()); return 0; } ``` #### 4. 操作函数 `std::forward_list` 提供了一系列操作函数来管理其元素,包括插入、删除、遍历等。 - **插入操作**: - `push_front`:在头部插入一个元素。 - `emplace_front`:在头部构造一个元素。 - `insert_after`:在指定位置之后插入一个或多个元素。 - **删除操作**: - `pop_front`:删除头部元素。 - `erase_after`:删除指定位置之后的一个或多个元素。 - **其他操作**: - `before_begin`:返回一个特殊的迭代器,用于表示第一个元素之前的虚拟位置。 - `empty`:检查列表是否为空。 - `merge`:将两个已排序的 `std::forward_list` 合并为一个。 ```cpp #include <iostream> #include <forward_list> int main() { std::forward_list<int> fl = {3, 1, 4, 1, 5}; // 在头部插入元素 fl.push_front(9); // 删除头部元素 fl.pop_front(); // 插入元素到指定位置之后 auto it = fl.begin(); ++it; // 移动到第二个元素之后 fl.insert_after(it, 2); // 遍历并输出元素 for (const auto& elem : fl) { std::cout << elem << " "; } std::cout << std::endl; return 0; } ``` #### 5. 常见问题 ##### Q: 如何遍历 `std::forward_list`? A: 由于 `std::forward_list` 不支持随机访问,只能通过迭代器从前向后遍历[^4]。 ```cpp for (auto it = fl.begin(); it != fl.end(); ++it) { std::cout << *it << " "; } ``` ##### Q: `std::forward_list` 是否支持尾部插入? A: 不支持直接的尾部插入操作。如果需要在尾部插入元素,可以通过 `insert_after` 和 `before_begin` 结合使用来实现。 ```cpp fl.insert_after(std::prev(fl.end()), 6); ``` ##### Q: `std::forward_list` 和 `std::list` 的主要区别是什么? A: `std::forward_list` 是单向链表,而 `std::list` 是双向链表。`std::forward_list` 不维护尾指针,因此更节省内存,但无法在常数时间内访问最后一个元素[^1]。 ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值