c++ - move 构造函数的这种实现会丢弃 move 语义吗?

标签 c++ move-semantics

如果我有一个像这样的 C 类:

class C {
    std::string s;

public:
    C(std::string&  s) : s(s) {}
    C(std::string&& s) : C(s) {}
};

我是否通过从 string&& 构造函数调用 string& 构造函数来丢弃 move 语义?

最佳答案

是的,您正在抛弃您的 move 语义。我可以提供的最直接的方法是通过示例来演示。这是我能想到的最明智的事情,所以我希望清楚发生了什么。

考虑一下:

#include <iostream>

struct S
{
    int x;

    S() :x(1) { std::cout << __PRETTY_FUNCTION__ << '\n';}
    S(const S& s) : x(s.x) { std::cout << __PRETTY_FUNCTION__ << '\n';}
    S(S&& s) : x(std::move(s.x)) { ++x, s.x=0; std::cout << __PRETTY_FUNCTION__ << '\n';}
    ~S() { std::cout << __PRETTY_FUNCTION__ << ':' << x << '\n';}
};

class C {
    S s;

public:
    C(S& s) : s(s) { std::cout << __PRETTY_FUNCTION__ << '\n';}
    C(S&& s) : C(s) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    ~C() { std::cout << __PRETTY_FUNCTION__ << '\n';}
};

int main()
{
    C c{S{}};
}

输出

S::S()
S::S(const S &)
C::C(S &)
C::C(S &&)
S::~S():1
C::~C()
S::~S():1

请注意,S两个 实例是通过 move 构造的,都不是。任何“move ”到预期目标的 S 都会为 x 打印 0。没有。第一个 SS{} 的初始临时值;第二个是通过 C(C&&) 初始化列表调用 C(C&) 生成的拷贝。这段代码完成后,当我们开始沿着析构函数链向下运行时,两个完全构造的 S 已经存在。

现在看看这个,相同的代码,但在 s 成员上使用了 move 语义:

#include <iostream>

struct S
{
    int x;

    S() :x(1) { std::cout << __PRETTY_FUNCTION__ << '\n';}
    S(const S& s) : x(s.x) { std::cout << __PRETTY_FUNCTION__ << '\n';}
    S(S&& s) : x(std::move(s.x)) { ++x, s.x=0; std::cout << __PRETTY_FUNCTION__ << '\n';}
    ~S() { std::cout << __PRETTY_FUNCTION__ << ':' << x << '\n';}
};

class C {
    S s;

public:
    C(S& s) : s(s) { std::cout << __PRETTY_FUNCTION__ << '\n';}
    C(S&& s) : s(std::move(s)) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    ~C() { std::cout << __PRETTY_FUNCTION__ << '\n';}
};

int main()
{
    C c{S{}};
}

输出

S::S()
S::S(S &&)
C::C(S &&)
S::~S():0
C::~C()
S::~S():2

S 的两个实例仍然被构造,但后者是通过 move 构造,吸收第一个这样做。当我们开始销毁所有这些东西时,只有一个 S 实例仍然有效;另一个因搬家而死亡。

长话短说,如果你的目标在 move ,你就是在开枪。我希望有帮助,但如果没有帮助,我完全愿意扔掉它。

关于c++ - move 构造函数的这种实现会丢弃 move 语义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24773636/

相关文章:

c++ - Segmentation Fault,归并排序算法

c++ - 在 C++ 中比较给定值的指针

c++ - 为 const 引用和右值引用编写重载

c++ - CMake:将头文件复制到输出目录

c++ - 如何在运行时在 OpenCL 中获取计算单元 ID?

c++ - int(floatvar) 和 (int)floatvar 之间有区别吗?

c++ - 重铸空指针容器

c++ - 使用 const 对象 move 语义

c++ - move 指针有什么好处吗?

C++:在不复制/move 太多的情况下解压缩具有引用和值的元组