使用引用进行高效交换?
Efficient Swap Using References?
我一直在阅读移动语义,我相信一个真正有效的交换如下(为了方便起见,我们现在将所有内容保留为 int 而不是使用泛型):
void swap(int& a, int& b) {
int tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}
这是正确的交换实现(对于整数)对吧?第 2 行不会在 RAM 中为tmp
创建额外的项目,对吧?
我的另一个问题是,使用引用而不是 std::move 的相同代码是否也像上面的 Move 语义示例一样出色(例如,不为tmp
创建额外的变量)?
void swap(int& a, int& b) {
int tmp = &a;
a = &b;
b = &tmp;
}
上面的代码是否为tmp
创建了一个额外的变量?它是否正确交换a
和b
?
内置类型没有移动构造函数或移动赋值运算符,因此您的第一个版本实际上与
void swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
您的第二个版本无法编译。但是,最有可能的是,您只是想写与我上面的版本相同的内容。两个版本都引入了一个名为tmp
的临时变量,以保留需要分配给一个交换值的值,而另一个交换值已更改。
不要假设代码中的每个构造(例如变量)在生成的机器代码中只有一个相应的构造(例如"RAM 中的额外项"),它总是会导致。这不是现代编译器的工作方式。编译器的工作不是获取每一行源代码,并使用特定的机器指令序列执行 1:1 替换。编译器的工作是获取您用C++语言描述的整个程序,并生成一个等效的程序,例如机器代码,当执行时,其行为方式与C++源代码描述的程序的行为无法区分。
如果您查看生成的程序集,您会发现,在交换纯整数的情况下,没有理智的编译器会将此临时变量移动到内存,而是使用寄存器来交换值。您可以相信编译器知道在给定目标体系结构上交换两个整数的最有效方法是什么。如果你不能相信你的编译器知道这一点,那么你应该寻找一个更好的编译器......
实际上,仅仅通过单独查看它生成的代码,很难真正说明这个swap
函数的"效率"有多大。在实践中,上述swap
这样的功能通常应该完全优化。它通常会在机器代码中留下的唯一痕迹是它对数据流的影响(此处的示例),但永远不会有实际的调用指令来调用单独的机器代码来执行交换。在优化swap
时,真正重要的事情是确保编译器实际上可以对其进行优化(这通常归结为确保无论在哪里使用它都是已知的定义)。
故事的寓意:不要专注于描述你认为机器代码应该如何工作,而是以一种你和编译器都可读的方式表达你的意图,首先,以一种基于语言规则而不是目标硬件规则正确描述预期行为的方式。永远不要依赖你认为某种语言在机器级别构建映射的内容。依靠C++语言对某种语言结构引起的行为的看法。现代C++编译器非常擅长将复杂的C++代码转换为非常精简和高效的机器代码,这些机器代码可以精确地执行C++中表达的内容。然而,他们通过积极利用这样一个事实来做到这一点,即所表达的行为也是唯一必须尊重的行为。因此,现代C++编译器非常不擅长生成机器代码,这些机器代码不是编写的内容,而只是在编写时思考......
使用引用进行交换将如下所示:
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
您只在声明它是引用时放置&
,但在使用它时不会。引用可以像常规变量一样使用。
因为您使用的是 ints,所以此交换与使用std::move
的交换一样高效。移动语义仅在使用拥有资源的类时提供好处。
例如,向量拥有一个指向数组的指针,因此移动向量比复制向量效率高得多,因为当您复制向量时,您必须复制向量内部数组中的所有数据。另一方面,如果您移动向量,则不必复制内部数组。它只需要将指针复制到数组,这要快得多。
- C++中高效的大型稀疏块压缩线性方程
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- C++嵌套if语句,基本货币交换
- shell排序中的交换和比较
- 如何在C++中高效地构造随机骰子
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 通过交换元素使数组相同
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 交换运算符 + 重载会导致无限递归
- 为什么 std::reduce 需要交换性?
- 复制和交换习惯用法与移动操作之间的交互
- C++ - 没有自定义交换功能的移动分配运算符?
- 如何在数组中交换最小和最大的位置?
- 尽管一切看起来都很好,但值不会交换
- C++交换来自同一类成员的参数值,处理多个类
- 更高效地在微控制器上对C++进行基准测试
- 对象内部有大量数据容器,实现更高效的对象交换
- 使用引用进行高效交换?
- 尽可能高效地交换字节