构造函数 - 复制常量引用 VS 移动复制值

Mił*_*zyn 1 c++ constructor

我找不到答案,所以我在这里提问。这有什么区别:

class Foo
{
public:
    Foo(std::string string)
        : m_String(std::move(string)) {}

private:
    std::string m_String;
}
Run Code Online (Sandbox Code Playgroud)

然后:

class Bar
{
public:
    Bar(const std::string& string)
        : m_String(string) {}

private:
    std::string m_String;
}
Run Code Online (Sandbox Code Playgroud)

我知道使用构造函数 fromBar可以准确地从值复制数据,但我真的不知道调用Foo构造函数时到底会发生什么。使用Fooor的构造函数有区别吗Bar

for*_*818 5

不要使用字符串,而是使用可以观察复制和移动的类型:

#include <iostream>

struct test {
    test() { std::cout << "constructor\n"; }
    test(const test&) { std::cout << "copy\n";}
    test(test&&) { std::cout << "move\n"; }
};

class Foo {
public:
    Foo(test t) : t(std::move(t)) {}    
private:
    test t;
};

class Bar {
public:
    Bar(const test& t) : t(t) {}   
private:
    test t;
};

int main() {
    test t1;
    Foo f{t1};
    std::cout << "...........\n";
    test t2;
    Bar b{t2};
}
Run Code Online (Sandbox Code Playgroud)

输出

constructor
copy
move
...........
constructor
copy
Run Code Online (Sandbox Code Playgroud)

调用Foos 构造函数t1会复制到构造函数参数,因为它是按值获取的,然后从参数移动构造成员。

调用Bar构造函数需要一个引用(不复制,不移动)并使用它来复制构造成员。


如果目的是避免复制,您将提供一个采用以下格式的构造函数test&&

struct Baz {
    Baz(test&& t) : t(std::move(t)) {}
    test t;
};
Run Code Online (Sandbox Code Playgroud)

然后Baz z(test{});将构造一个test并且成员将从该临时构造移动。不涉及副本。