引用成员是一个好的编程实践吗?常量成员呢?

4
我和我的同事正在辩论const或引用成员是否适用。const和引用成员会使类不可复制,也不能移动,除非您编写自己的复制和移动操作符,忽略引用或常量成员。我找不到忽略某些成员的复制或移动的情况,只因为它们是引用或常量而有意义。
我认为拥有不可移动对象在逻辑上很少有意义,这只与类是否位置不变有关。不可复制的对象更为常见,但使类不可复制的选择与其是否持有逻辑上不可复制的资源,是否表示唯一所有权等有关。我想不出仅具有引用或常量成员与否的类应该具有这些特性(不可复制或不可移动)的原因。
它们是否应该被使用?应该使用其中一个而不是另一个吗?有哪些例子?

1
我认为他们没有将该类设置为不可复制或不可移动;它不能被复制/移动,但肯定可以从中复制/移动。它更像是“不可分配”的而不是“不可复制的”。 - Angew is no longer proud of SO
1
我发现引用成员在像函数对象这样的事情上非常有用。 - Vaughn Cato
1
关于不可移动对象的好奇声明。我认为通常没有理由使对象可移动。当然,实体对象永远不应该是可移动的,因为它们从不作为临时对象出现。而使具有值语义的对象可移动是一种优化,不一定适用于许多类型,并意味着显著的可移植性损失(至少在今天),以及增加的复杂性。事实上,我认为只有在分析器说需要时才应使用可移动。 - James Kanze
我赞同 Vaughn Cato 的观点。 - Anon Mail
1个回答

5
我想不出一个理由,拥有引用或const成员或没有这些特性之一就意味着该类应具有这两个特性(不可复制或不可移动)。 我认为这个前提是错的。
拥有const数据成员或引用数据成员并不会使类不可复制:它只是使它不可能以破坏性的方式进行赋值或移动。
那是因为对于const对象或引用来说,破坏性的移动操作是不可靠的:它会违反它们的语义,因为const对象的状态不应该被改变,而引用不能被解绑定。
但是,X不可复制或不可移动并不妨碍构造这些对象的副本的可能性,正如您指出的那样。例如,以下程序将编译成功:
struct X
{
    X() : x(0), rx(x) { }

    const int x;
    const int& rx;
};

int main()
{
    X x;
    X x1 = x; // Copy-initialization (copy-constructs x1 from x)
    X x2 = X(); // Copy-initialization (copy-constructs x2 from a temporary)
}

编译器会自动为您生成一个复制构造函数,而移动操作将退化为复制操作。如果这种移动到复制的退化对于您的类的语义不合适,则可以考虑不使用const或引用成员。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接