C++ 是否可以创建一个只有常量/引用成员的可移动类?
一切都有问题。我试过:C++ 是否可以创建一个只有常量/引用成员的可移动类?,c++,C++,一切都有问题。我试过: #include <vector> class Foo { int & _x; public: Foo(int x) : _x(x) {} Foo(Foo && other) : _x(other._x) {} Foo & operator=(Foo && othe
#include <vector>
class Foo
{
int & _x;
public:
Foo(int x) :
_x(x)
{}
Foo(Foo && other) :
_x(other._x)
{}
Foo & operator=(Foo && other) = default;
private:
Foo(Foo const &) = delete;
Foo & operator=(Foo const &) = delete;
};
int main(void)
{
int a, b;
std::vector<Foo> vec;
vec.push_back(Foo(a));
vec.push_back(Foo(b));
vec.erase(vec.begin());
return 0;
}
#包括
福班
{
int&ux;
公众:
Foo(int x):
_x(x)
{}
Foo(Foo&其他):
_x(其他)
{}
Foo&operator=(Foo&other)=默认值;
私人:
Foo(Foo const&)=删除;
Foo&运算符=(Foo const&)=删除;
};
内部主(空)
{
INTA,b;
std::vec;
向量推回(Foo(a));
向量推回(Foo(b));
向量擦除(vec.begin());
返回0;
}
但是它无法编译,因为默认情况下删除了Foo&operator=(Foo&other)
我试图删除这个操作符,通过move强制编译器使用构造函数,但它试图使用copy构造函数
是否可以移动具有引用成员的对象
若否,原因为何
谢谢
编辑:我已经读过了,但它没有回答我的问题:我想知道为什么编译器使用Foo&operator=(Foo-const&)
,而Foo(Foo&other)
可以工作
我无法理解为什么不能移动带有引用成员的类。您的问题是需要元素类型为。这仅仅是因为擦除
通常的实现方式:它在被擦除的元素(或多个元素)之后遍历向量,移动分配到被擦除的插槽:
for (; j != end; ++i, ++j)
*i = std::move(*j);
for (; i != end; ++i)
i->~T();
这可以通过使用移动构造以不同的方式实现,但如果存在移动分配操作符(大多数情况下是这样),并且很难获得异常安全,则这将是低效的:
for (; j != end; ++i, ++j)
{
i->~T();
new (&*i) T(std::move(*j)); // what if this throws?
}
for (; i != end; ++i)
i->~T();
您可以通过使用另一种策略来解决此问题,以获得擦除
的效果,例如:
vec = std::vector<Foo>(
std::make_move_iterator(std::next(vec.begin())),
std::make_move_iterator(vec.end()));
vec=std::vector(
std::make_move_迭代器(std::next(vec.begin()),
std::make_move_迭代器(vec.end());
Foo
仍然不是很有用,这正是因为带有引用成员的类型不能是move-assignable();您应该考虑是否可以使用<代码> RealthyWraseBuffer-<代码>。具有引用成员的类可以被复制构造和移动构造,但不能被复制指派或移动指定。问题不在于移动,问题在于赋值(运算符=),为什么std::vector使用运算符=而不是移动构造函数?他们不是有相同的行为吗?不是。一个构造,另一个赋值。vector为push_back
使用构造函数,但erase
需要赋值。我希望我的引用是公共的(或使用type*const
):这样每个人都可以使用它,而无需修改地址值。但是引用包装器不起作用,因为我们必须使用get()
。