右值的 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);
}
我正在尝试设置一个模板来交换数组,以便在许多 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);
}