gpt4 book ai didi

c++ - 使用右值引用和简单工厂

转载 作者:搜寻专家 更新时间:2023-10-31 01:02:54 24 4
gpt4 key购买 nike

我最近了解了 std::movervalue 引用,想知道我对它们的使用是否既合适又高效。

考虑这个简单的 Image 类,它只存储一个表示像素的 unsigned char 值数组。 (请注意,实际上成员数多于单个字符数组,但为了便于阅读,我在这里进行了简化。)

using PixelContainer = std::vector<unsigned char>;

class Image {
public:
Image(PixelContainer&& pixels) : m_pixels(std::move(pixels)) {};

Image& operator=(Image&& image) { m_pixels = std::move(image.m_pixels); return *this; };

private:
PixelContainer m_pixels;
};

现在考虑 ImageFactory 类的这个静态方法,它接受 .png 的文件名并返回一个 Image 对象适当的像素值。

Image ImageFactory::loadImage(const char* filename) {
PixelContainer temp_pixels;

// ... fill pixels from file (details not relevant here)

Image temp_image(std::move(temp_pixels));

return temp_image;
}

最后,它们一起用于代码中:

Image image = ImageFactory::loadImage("image.png");

我正在使用 rvalue 引用,大概是为了摆脱复制可能是大量像素值的拷贝所花费的时间。因为工厂创建的 vector 和图像是临时的,所以它们可以四处移动。

我的问题是,我的实现是否有意义,如果没有根本性的缺陷,是否可以进一步改进?

最佳答案

让我们一探究竟!我添加了一个这样的函数来包含你的最后一点代码:

Image outer() {
Image image = ImageFactory::loadImage("image.png");
return image;
}

我还必须为 Image 添加一个常规的复制构造函数(我使用 = default 来定义它),因为即使它没有被实际使用,它也是需要按值返回。

然后我使用 Clang -O2 -g -S 进行了编译,并查看了程序集。它主要是初始化 vector 的代码:调用 operator new 并设置 vector 的内部指针。没有复制,代码看起来相当干净和高效。正如您可能希望的那样,outer() 的代码与 loadImage() 的代码几乎相同(后者内联到前者中,因为我将所有内容都放在一个翻译单元)。

作为引用,这是我得到的程序集:

outer():                             ## @_Z5outerv
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl $100000000, %edi ## imm = 0x5F5E100
callq operator new(unsigned long)
movd %rax, %xmm0
movlhps %xmm0, %xmm0 ## xmm0 = xmm0[0,0]
movq $-100000000, %rcx ## imm = 0xFFFFFFFFFA0A1F00
movq %rax, %rsi
LBB1_1: ## =>This Inner Loop Header: Depth=1
testq %rsi, %rsi
movl $0, %edx
je LBB1_3
movb $0, (%rsi)
movaps %xmm0, %xmm1
punpckhqdq %xmm1, %xmm1 ## xmm1 = xmm1[1,1]
movd %xmm1, %rdx
LBB1_3: ## %_ZNSt3__116allocator_traits...
incq %rdx
movd %rdx, %xmm1
punpcklqdq %xmm1, %xmm0 ## xmm0 = xmm0[0],xmm1[0]
incq %rcx
movq %rdx, %rsi
jne LBB1_1
## BB#4: ## %_ZN12ImageFactory9loadImageEPKc.exit
leaq 100000000(%rax), %rax
movdqu %xmm0, (%rbx)
movq %rax, 16(%rbx)
movq %rbx, %rax
addq $8, %rsp
popq %rbx
popq %rbp
retq

关于c++ - 使用右值引用和简单工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26310367/

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