我不知道如何将C++std::unique_ptr::swap
翻译成Go。
我正在使用std::unique_ptr<T、 删除程序>:C++中的交换:
std::unique_ptr<bool[]> maskA{new bool[num]};
std::unique_ptr<bool[]> maskB{new bool[num]};
// ...
maskA.swap(maskB); // Swap operation
如果我只是在Go中使用一个简单的maskA, maskB = maskB, maskA
,我会错过什么吗?
maskA := make([]bool, num)
maskB := make([]bool, num)
// ...
maskA, maskB = maskB, maskA
此交换是否具有相同的功能?
简短答案:
这在功能上是等效的,但实际的性能影响是不同的。使用*[]bool
表示最接近的等价物。
属性:
带有交换的分配具有以下属性:
maskA
和maskB
的值将被交换- 因为这些是切片,所以布尔的底层数组是而不是复制
- 由于编译器的优化,切片描述符也可能不会被复制
由于切片的构建方式,最后两点很重要:它们是指向底层数组的小描述符。有关更多详细信息,请参阅切片内部。
C++和Go之间的区别:
在C++中,unique_ptr<foo>
始终包含*foo
,而交换仅涉及交换地址,这具有可预测的性能影响。
在Go中,类型是您给定的任何类型,编译器将复制值。工作量取决于类型:
- 如果这些是大的(例如:arrays:
[1000]bool
(,可能会变得昂贵 - 如果它们是您现在拥有的切片(例如:
[]bool
(,则会复制切片描述符 - 如果它们是指针(例如:
*[]bool
(,这将与C相同++
因此,为了保证与C++代码等效,您应该使用指向布尔切片的指针(*[]bool
(作为Go类型。
Go优化:
Go编译器将尝试优化掉变量交换。
这里有一个微不足道的例子:
func main() {
a := make([]bool, 0)
b := make([]bool, 0)
fmt.Println(a, b)
a, b = b, a
fmt.Println(a, b)
}
我们可以使用GOSSAFUNC=main go build .
在编译过程中转储优化步骤
查看生成的ssa.html
文件,我们可以看到a, b = b, a
行被完全删除,下面的代码被更改为类似fmt.Println(b, a)
的代码。
当这种情况发生时,交换只是编码的精细性,没有性能影响,但情况并非总是如此(编译器优化非常专业,有些情况下它无法做到这一点。例如:交换两个结构字段成员无法优化(。
不平等比较:
将两者进行比较有点奇怪。C++中的一个更接近的等价物是要交换的两个普通变量(无论是否为指针(。unique_ptr
的主要目标是简化对象所有权,并在unique_ptr
超出范围时删除底层对象。
Go没有unique_ptr
的等价物,主要是因为它不需要,所有内存都是垃圾收集的。