右值的 C++11 字段是右值

C++11 field of rvalue is a rvalue

我正在尝试设置一个模板来交换数组,以便在许多 classes 的移动构造函数中使用:

template <class T> void tools_swap_array(T* & a, T* & b) noexcept
{
    auto tmp(a);
    a = b;
    b = tmp;
}

现在我想在移动构造函数中使用它,并通过一个名为 move_from():

的通用方法移动赋值运算符
void label::move_from(label && ref) noexcept  
{
    tools_swap_array((char *)val, (char*)ref.val);
}

其中 val 是 class 标签的字段:

class label
{
public:
    // [...]
    label(label && ref) { move_from(std::move(ref)); };
    label & operator = (label && ref) { move_from(std::move(ref)); return *this; };
    // [...]
private:
    char val[LABEL_SIZE];
};

但是当我 运行 编译器时,它在 move_from() 中失败告诉 ref.val 是一个右值

error: invalid initialization of non-const reference of type 'char*&'
from an rvalue of type 'char*'  
tools_swap_array((char *)val, (char*)ref.val);
                                            ^

我认为 "label && ref" 是 move_from() 中的左值,"ref.val" 也是。那么,我是否仍然误解了 C++11 对右值的引用,或者这是一个编译器错误?

感谢任何提示!

正确的实现方式是完全不自己写swap函数。 std::swap() 在 C++11 及更高版本中有固定大小数组的重载,请改用它,例如:

#include <utility>

void label::move_from(label && ref) noexcept  
{
    std::swap(val, ref.val);
}

如果你真的想手动实现数组交换功能,你需要传递对实际数组的引用,而不是传递指针给它们(只交换指针根本不会交换数组元素),例如:

#include <algorithm>

template <class T, std::size_t N>
void tools_swap_array(T (&a)[N], T (&b)[N]) noexcept
{
    T tmp[N];
    std::copy_n(a, N, tmp);
    std::copy_n(b, N, a);
    std::copy_n(tmp, N, b);
}

或:

#include <utility>

template <class T, std::size_t N>
void tools_swap_array(T (&a)[N], T (&b)[N]) noexcept
{
    for(std::size_t i = 0; i < N; ++i)
        std::swap(a[i], b[i]);
}

或者(这基本上就是 std::swap() 所做的):

#include <algorithm>

template <class T, std::size_t N>
void tools_swap_array(T (&a)[N], T (&b)[N]) noexcept
{
    std::swap_ranges(a, a+N, b);
}

不管怎样,你可以这样做:

void label::move_from(label && ref) noexcept  
{
    tools_swap_array(val, ref.val);
}