gpt4 book ai didi

c++ - 通过调用 move 赋值运算符实现 move 构造函数

转载 作者:IT老高 更新时间:2023-10-28 22:13:24 26 4
gpt4 key购买 nike

MSDN 文章,How to: Write a Move Constuctor ,有以下推荐。

If you provide both a move constructor and a move assignment operator for your class, you can eliminate redundant code by writing the move constructor to call the move assignment operator. The following example shows a revised version of the move constructor that calls the move assignment operator:

// Move constructor.
MemoryBlock(MemoryBlock&& other)
: _data(NULL)
, _length(0)
{
*this = std::move(other);
}

通过双重初始化 MemoryBlock 的值,这段代码是否效率低下,或者编译器是否能够优化掉额外的初始化?我是否应该总是通过调用 move 赋值运算符来编写 move 构造函数?

最佳答案

[...] will the compiler be able to optimize away the extra initializations?

在几乎所有情况下:是的。

Should I always write my move constructors by calling the move assignment operator?

是的,只需通过 move 赋值运算符实现它,除非您测量它会导致性能欠佳。


今天的优化器在优化代码方面做得非常出色。您的示例代码特别容易优化。首先: move 构造函数在几乎所有情况下都会被内联。如果您通过 move 赋值运算符实现它,则该运算符也将被内联。

让我们看看一些组装! This显示了来自 Microsoft 网站的确切代码,其中包含两个版本的 move 构造函数:手动和通过 move 赋值。这是带有 -O 的 GCC 的汇编输出(-O1 具有相同的输出;clang 的输出导致相同的结论):

; ===== manual version =====           |   ; ===== via move-assig =====
MemoryBlock(MemoryBlock&&): | MemoryBlock(MemoryBlock&&):
mov QWORD PTR [rdi], 0 | mov QWORD PTR [rdi], 0
mov QWORD PTR [rdi+8], 0 | mov QWORD PTR [rdi+8], 0
| cmp rdi, rsi
| je .L1
mov rax, QWORD PTR [rsi+8] | mov rax, QWORD PTR [rsi+8]
mov QWORD PTR [rdi+8], rax | mov QWORD PTR [rdi+8], rax
mov rax, QWORD PTR [rsi] | mov rax, QWORD PTR [rsi]
mov QWORD PTR [rdi], rax | mov QWORD PTR [rdi], rax
mov QWORD PTR [rsi+8], 0 | mov QWORD PTR [rsi+8], 0
mov QWORD PTR [rsi], 0 | mov QWORD PTR [rsi], 0
| .L1:
ret | rep ret

除了正确版本的附加分支外,代码完全相同。含义:重复的分配已被删除

为什么要增加分支? Microsoft 页面定义的 move 赋值运算符比 move 构造函数做更多的工作:它可以防止自赋值。 move 构造函数不受此保护。 但是:正如我已经说过的,构造函数在几乎所有情况下都会被内联。而且在这些情况下,优化器可以看出它不是自赋值,所以这个分支也会被优化掉。


这个 get 重复了很多次,但很重要:不要过早进行微优化!

不要误会我的意思,我也讨厌由于懒惰或草率的开发人员或管理决策而浪费大量资源的软件。而节能不仅仅是电池,也是一个我非常热衷的环保话题。 但是,过早地进行微优化在这方面没有帮助!当然,将大数据的算法复杂性和缓存友好性放在脑后。但在进行任何特定优化之前,请测量!

在这种特定情况下,我什至猜想您永远不必手动优化,因为编译器将始终能够围绕您的 move 构造函数生成最佳代码。现在进行无用的微优化将花费您以后的开发时间,因为您需要在两个地方更改代码,或者当您需要调试一个奇怪的错误时,该错误只会因为您只在一个地方更改代码而发生。这是浪费的开发时间,本可以花在有用的优化上。

关于c++ - 通过调用 move 赋值运算符实现 move 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17118256/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com