gpt4 book ai didi

c++ - std::move 在 move 到左值引用时会导致切片吗?

转载 作者:太空狗 更新时间:2023-10-29 19:47:33 25 4
gpt4 key购买 nike

请看下面的代码:

#include <iostream>
#include <chrono>

class Parent
{
public:
Parent() = default;
virtual ~Parent() = default;
Parent(const Parent& pr) : i{pr.i} {std::cout << "Parent copy constructor\n";}
Parent& operator=(const Parent& pr) {std::cout << "Parent copy assignment\n"; this->i = pr.i; return *this;}
Parent(Parent&& pr) : i{std::move(pr.i)} {std::cout << "Parent move constructor\n";}
Parent& operator=(Parent&& pr) {std::cout << "Parent move assignment\n"; this->i = std::move(pr.i); return *this;}

virtual void print_i_j() = 0;

int i = 10;
};

class Child : public Parent
{
public:
Child() = default;
Child(const Child& cr) : Parent{cr}, j{cr.j} {std::cout << "Child copy constructor\n";}
Child& operator=(const Child& cr) {std::cout << "Child copy assignment\n"; this->j = cr.j; return *this;}
Child(Child&& cr) : Parent{std::move(cr)}, j{std::move(cr.j)} {std::cout << "Child move constructor\n";}
Child& operator=(Child&& cr) {std::cout << "Child move assignment\n"; Parent::operator=(std::move(cr)); this->j = std::move(cr.j); return *this;}

void print_i_j() {std::cout << "i = "<< i << " j = " << j << std::endl;}

int j = 100;
};

int main(int argc, const char * argv[])
{
Child c;
c.i = 30;
c.j = 300;
c.print_i_j();

Child c2; // leave c2 with defaults (i=10, j=100)
Parent& p_ref = c2;
p_ref.print_i_j();

c2.j = 150;
p_ref.print_i_j();

p_ref = std::move(c); // (1)
p_ref.print_i_j(); // (2)

return 0;
}

当我运行它时,我得到:

i = 30 j = 300
i = 10 j = 100
i = 10 j = 150
Parent move assignment
i = 30 j = 150

据我所知,如输出所示,i 的变化是由于将派生类的实例 move 到对父类的引用中,但是 j 没有。

(2) 中打印的结果是否表明 (1) 中的 move 导致了切片?还是其他一些行为(甚至未定义的行为)开始起作用?

最佳答案

Can std::move cause slicing ...

没有。 std::move 不会导致切片。

但是,赋值到基础对象会导致切片,即只有基础被赋值,对象的其余部分不受影响。这在复制分配和 move 分配时都会发生。然而, move 赋值确实有一个额外的考虑:不仅分配了左手操作数的基数(就像在复制的情况下),而且还只 move 了右手操作数的基数。

无论基数是否通过引用赋值都不会影响切片,除非赋值运算符是虚拟的(尽管不要使用虚拟赋值运算符;它们不是一个简单/好的解决方案)。


或者:

  • 确保派生类可以处理从基础子对象分配/move 的对象(即,不应存在此类分配可能违反的类不变量)。
  • 或者让 base 不可分配(也许让分配受到保护)。
  • 或者使基地不可访问( protected 或私有(private))

在任何情况下,确保左侧操作数的静态类型是您在分配时期望的类型。

关于c++ - std::move 在 move 到左值引用时会导致切片吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56077078/

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