【问题标题】:Calling a function that moves the parameter value in a function that copies it调用在复制它的函数中移动参数值的函数
【发布时间】:2020-11-24 21:34:02
【问题描述】:

我通过以下代码:

void enqueue(T&& value)
{
    move_value_somewhere( T(std::move(value)));
}

void enqueue(const T& value)
{
    enqueue(T(value));
}

复制输入参数的第二个函数调用移动它的第一个函数。假设代码是正确的,如果从第二个函数调用T(std::move(value)) 不移动值而不是复制它,它可能来自T(),但我不知道为什么。

【问题讨论】:

    标签: c++ c++11 move-semantics


    【解决方案1】:

    enqueue(T(value)); 中,您首先创建传递值的临时副本 (T(value))。然后,您的移动构造函数 enqeue 会移动该临时副本。所以该代码类似于

    T copy(value);
    enqueue(std::move(copy));
    

    【讨论】:

      【解决方案2】:

      enqueue() 采用 T&&,它只是将其限制为该类型,不会因为传递参数而发生构造函数调用,因为它不是值类型。

      但是,当您调用 enqueue() 时,您会创建一个临时的 T,它将从您传递给它的 const T& value 调用其复制构造函数。

      随后,临时变量成为enqueue() 的参数,然后创建另一个prvalue T,这一次使用您的(现在)左值参数初始化为T&&,如果T 确实有一个移动构造函数,将调用它。

      否则,如果T 没有移动构造函数(也没有显式删除的构造函数),它将“回退”以调用复制构造函数(如果存在)。

      由于您将临时传递给move_value_somewhere(),因此它需要接受T&&const T&T——前提是T 类型有一个可行的构造函数来使这一切成为可能。

      【讨论】:

        【解决方案3】:

        void enqueue(const T& value) 中,一个临时的T 正在从value 复制构造为输入。然后将该临时文件传递给void enqueue(T&& value)

        void enqueue(T&& value) 中,另一个临时的T 正在从value 作为输入移动构造(假设T 有移动构造函数,否则它将被复制构造)。然后将该临时文件传递给move_value_somewhere()。那个临时的T实际上是不必要的,因为value已经是一个右值引用,所以可以直接移动到move_value_somewhere(),例如:

        void enqueue(T&& value)
        {
            move_value_somewhere(std::move(value));
        }
        

        复制构造函数内部调用移动构造函数

        实际上并非如此,因为显示的代码根本不适用于构造函数,只是用于普通的非静态类方法。那里有很大的不同。 构造函数没有返回值,并且不能像这段代码那样互相调用。但是他们可以委托给对方,但只能从成员初始化列表中。见Constructors and member initializer lists

        【讨论】:

        • 抱歉误导,是的,这是正常的方法而不是构造函数。
        • 由于上述代码调用复制构造函数而不是移动值,如果该函数直接复制数据会更快吗?假设我们有像copy_value_somewhere()这样的函数。
        • 如果您要同时接受复制和移动的输入,通常最好只有一个版本的enqueue() 接受T 按值 和获取该数据的所有权,例如:void enqueue(T value) { move_value_somewhere(std::move(value)); } 这让 调用者 决定是否根据需要使用复制或移动语义构造 value 参数。
        猜你喜欢
        • 1970-01-01
        • 2015-01-04
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-21
        相关资源
        最近更新 更多