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

推荐订阅源

S
Secure Thoughts
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
O
OpenAI News
GbyAI
GbyAI
L
LINUX DO - 最新话题
A
Arctic Wolf
T
Tor Project blog
G
GRAHAM CLULEY
I
InfoQ
博客园_首页
IT之家
IT之家
The Register - Security
The Register - Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
The GitHub Blog
The GitHub Blog
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
K
Kaspersky official blog
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
U
Unit 42
PCI Perspectives
PCI Perspectives
量子位
P
Palo Alto Networks Blog
S
Securelist
T
Troy Hunt's Blog
博客园 - 【当耐特】
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
Security Affairs
Engineering at Meta
Engineering at Meta
T
The Blog of Author Tim Ferriss
博客园 - 聂微东
罗磊的独立博客
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
NISL@THU
NISL@THU
C
Cisco Blogs
T
Threatpost
有赞技术团队
有赞技术团队
Forbes - Security
Forbes - Security
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
T
The Exploit Database - CXSecurity.com
Cloudbric
Cloudbric
Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
C
Cyber Attacks, Cyber Crime and Cyber Security

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,但我们毕竟是对真实的物理机操作,实际中是可以正确执行的。