尝试通过const成员传递引用时引用已删除的函数

时间:2017-03-07 19:49:49

标签: c++

我显然遗漏了一些东西。

如果我有:

class MyClass
{
public:
    const int something;

    MyClass(int Something) : something(something) {}
};

这将失败(尝试引用已删除的函数),因为我没有复制构造函数

std::vector<MyClass> myStuff;
std::sort(myStuff.begin(), myStuff.end(), 
    [](MyClass lhs, MyClass rhs) { 
        return lhs.something > rhs.something; });

所以我应该通过参考传递。但即使lambda变成

,我也有同样的问题
[](const MyClass& lhs, const MyClass& rhs) { 
    return lhs.something > rhs.something; });

这背后的原因是什么?解决方法很明确(没有const成员变量),但我想知道上面例子中我缺少的内容。

2 个答案:

答案 0 :(得分:2)

你的类有一个const成员,而你要求std :: sort基本上交换你的类的实例。与包含对象的句柄(垃圾收集指针)的Java ArrayList不同,C ++ STL容器直接包含对象本身。因此,您不能交换实例,因为这意味着要覆盖const对象。您的解决方案必须是以下之一:

  • 对指针或对对象的引用进行排序:如果您在其他地方有实例,则可以使用vector<MyClass*>vector<reference_wrapper<MyClass>>;如果向量拥有vector<unique_ptr<MyClass>> the instances。
  • 使字段非常量。然后你的类将有一个复制赋值运算符(和一个移动ctor / op =,但只有那个成员它将是相同的)
  • 提供自定义移动/复制op =使用const_cast来抛弃该字段的常量。这是一个的想法,因为标准说明它是未定义的行为(即编译器和程序可能会在某些情况下将您的计算机设置为火焰)。我不记得确切的标准,但你必须非常小心,不要陷入其中一个快乐的C ++未定义行为陷阱。

答案 1 :(得分:2)

std::sort要求迭代器指向的元素为MoveAssignableMoveConstructible。你的类是MoveConstructible但它不是MoveAssignable。原因是你有一个const成员。您无法分配或移动const成员,因为这是一项变异操作。您可以提供自己的副本或移动赋值运算符来解决此问题,或者只是使成员非常常。