std::move使用不当引起的copy elision

本文讨论了C++11中std::move的使用,指出不恰当的使用可能导致代码效率降低,因为它可能阻碍编译器的copy elision优化。当std::move在临时对象、return语句或特定初始化场景中使用时,可能实际上并无必要,甚至可能降低性能。文章提供非合规和合规代码示例,强调在不需要转移资源所有权时避免使用std::move以确保最佳性能。

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

在使用sonarqube检测C++项目代码时,发现一个使用std::move引起的code smell等级的告警,特记录。

  • 原文内容:
  • Usually, when copying an object, the source object is unchanged, which means that all resources owned by the source objects have to be duplicated during the copy operation. In the case that the source object will no longer be used, this duplication is not efficient. Since C++11, a mechanism named move semantic has been added to detect such cases and replace the expensive copy by a much cheaper move operation that will steal resources.
  • The cornerstone of move semantic is the ability to detect during a “copy” if the source object will be reused or not. There are three situations:
    • The object is a temporary object, with no name, and if it can’t be named, it can’t be used
    • The object is used in some specific places, such as a return statement
    • The user explicitly promises to the compiler that he won’t care for the current value of the object any longer. He does so by using the specific cast operation named std::move.
  • If the user write std::move in one situation that is already handled by the first two cases, it has two drawbacks:
    • It is clumsy, useless code, which make understanding the code more complex
    • In some cases, it can decrease performances, because this can deactivate another optimization of the compiler, named copy elision.
  • When copy elision occurs, the object is neither copied nor moved (even if the copy/move constructors have side effects), in fact, the two objects are collapsed into only one memory location. When copy elision occurs is compiler-dependent, but is mandatory(强制性的) in the following cases:
    • in a return statement if the returned object is a prvalue of the same class type as the function return type
    • in the initialization of a variable if the initializer expression is a prvalue of the same class type as the variable type
  • This rule reports an issue(即检测出的code smell)when the use of std::move prevents the copy elision from happening.
  • Noncompliant Code Example
class A {};
A getA();

A f() {
 A a = std::move(getA()); // Noncompliant, prevents copy elision
 vector<A> v;
 v.push_back(std::move(getA())); // Noncompliant
 return std::move(a); // Noncompliant, prevents copy elision
}
  • Compliant Solution
class A {};
void test(A a);

A f() {
 A a = getA(); // Compliant
 vector<A> v;
 v.push_back(getA()); // Compliant
 return a; // Compliant
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值