gpt4 book ai didi

c++ - 演示 move 构造函数的有用性

转载 作者:行者123 更新时间:2023-12-05 01:04:38 29 4
gpt4 key购买 nike

我试图证明 move 构造函数在消除不必要的复制方面的有用性。但是,当我在 Release 中运行时,Visual Studio 优化器会忽略拷贝。当 move 构造函数不可用时不会调用复制构造函数,显然添加一个时不会调用 move 构造函数。

我可以通过在 Debug 中运行来移除优化,但这并不能很好地证明需要 move 语义。

struct A { 
int *buff;
A() {
cout << "A::constructor\n";
buff = new int[1000000];
}
A(const A& a) {
cout << "A::copy constructor\n";
buff = new int[1000000];
memcpy(buff, a.buff, 1000000*sizeof(int));
}
A(A&& original)
{
cout << "Move constructor" << endl;
buff = original.buff;
original.buff = nullptr;
}
~A() { cout << "A::destructor\n"; delete[] buff; }
};

A getA()
{
A temp;
temp.buff[0] = 2;
return temp;
}
void useA(A a1) {
cout << a1.buff[0] << endl;
}

void main() {
useA(getA()); // i'd like copy-constructor to be called if no move constructor is provided
}

我可以在代码中更改什么以防止优化器取消复制,并说明添加 move 构造函数如何防止完整复制?

编辑:演示最好不需要明确的 move 调用/施法。

最佳答案

您遇到了命名返回值优化 (NRVO),这不是强制性的,并且要求复制/move ctor 可用。

为了演示零/三/五规则、 move 语义、RVO、复制省略,我将使用以下示例:

struct A{
char* large_buffer = new char[1024];

~A(){ delete[] large_buffer;}
};

struct D{
A a;
int b;
int* c;
};
D construct_D()
{
// Obtained somewhere
A a = {};
int b = 10;
int* c = new int[1024];

// Now we want to construct `D` which should "consume" the values.
D d{a,b,c};
// Perhaps do something with that before returning it.
return d;
}
int main(){
D dd = construct_D();
}

你现在可以解释了:

  1. b 被复制,没关系。
  2. A 被破坏,因为天真的复制 ctor 是成员明智的,并且会发生双重删除。 (如果不忘记添加D::~D)
  3. 可以通过三规则来解决。
  4. 使用规则五可以更有效,因为在构造 d 之后永远不会使用 a 并且如果它可以放弃其缓冲区并被“消耗”会更好.
  5. 解释 std::move 的作用,以实现这种消费。您可以交互地重写代码以将一些变量更改为临时变量并深入研究 r-value 语义。
  6. 编写五个函数很乏味,将 char* 替换为 std::vector 可以获得零规则,这很好。
  7. c 复制指针,而不是缓冲区,这在这种情况下是可取的,但很危险,因为有人必须稍后释放它以及 std::unique_ptr 如何解决这个问题,或 std::string,或再次 std::vector
  8. 现在有些学生可能会问 D 是否需要 0/3/5 以及我们如何解决这个问题。
  9. 您可以添加 3/5 并观察没有进行这些调用并解释 NVRO 和 RVO 的 return {a,b,c} 以及随后的 dd 构造>.
  10. 还有人总是会用 D dd 不调用赋值运算符来混淆某些人。
  11. 最后你可以争辩说 construct_D 太长了,所以你会交互地将它重构为更小的函数,同时使用所有学到的概念 - std::move,通过引用,值(value),RVO。

总的来说,您可以在这个示例上花费一两个小时,另外还可以传播 std:: 宣传关于 new 和原始指针的邪恶.

关于c++ - 演示 move 构造函数的有用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71725173/

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