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()