惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
Jina AI
Jina AI
博客园_首页
M
MIT News - Artificial intelligence
D
DataBreaches.Net
L
LangChain Blog
宝玉的分享
宝玉的分享
F
Fortinet All Blogs
A
About on SuperTechFans
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Y
Y Combinator Blog
腾讯CDC
Vercel News
Vercel News
雷峰网
雷峰网
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】

Jia Yue Hua

闲散颂 adapting c++20 ranges algorithms for most metaprogramming Reproducible github Developer Environments 使用mpmcpipeline和jthread实现软流水 在其它线程周期回调函数 在当前线程周期回调函数 for_each cpo和tag_invoke transparent,为关联容器增加查找成员
完美转发不完美
Jia Yue Hua · 2024-11-16 · via Jia Yue Hua

C++的完美转发并不完美,这是因为对于如下例子代码

struct Boulder{
 Boulder(){}
 Boulder(const Boulder&)=default;
 Boulder(Boulder&&)=default;
 Boulder& operator=(const Boulder&)=default;
 Boulder& operator=(Boulder&&)=default;
 ~Boulder(){}
};
void f(Boulder)
{}
template<class T>
void g(T&&t)
{
   f(std::forward<T>(t));
}

int main()
{
  f(Boulder{});
  g(Boulder{});
}

对于f函数调用,只调用Boulder的构造函数和析构。然而对于由g完美转发后在调用f时候,却不得不调用移动构造,因为f的函数参数是值类型,其参数现在为xvalue而不再是prvalue.

然而有一个技巧可以修复该问题,对于C++安腾ABI 而言,如果将f的参数改为右值引用,godbolt显示修改前后f将产生一样的汇编代码。 godbolt

因此如果想省去g中完美转发的开销,可以借助这一点,将g改写为

template<class T>
void g(T&&t)
{ 
   typedef void(*MyF)(Boulder&&);
   auto nf=reinterpret_cast<MyF>(&f);
   (*nf)(std::forward<T>(t));
}

这样*nf的参数是右值引用,省去了移动构造的开销。

上述g中的nf调用虽然理论上是UB,但我们毕竟是对真实的物理机操作,实际中是可以正确执行的。