2017-03-07 53 views
1

我明显错过了某些东西。尝试引用与const成员通过引用传递时删除的函数

如果我有:

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; }); 

所以我应该按引用传递。但即使拉姆达变为

[](const MyClass& lhs, const MyClass& rhs) { 
    return lhs.something > rhs.something; }); 

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

+3

'sort'需要移动向量中的物体。你不能这样做,因为课程不是可复制或可分配的。 – NathanOliver

+0

@NathanOliver而移动构造函数由于相同的原因而丢失,对吧? – user3804799

+0

是的,复制和移动赋值操作符被删除,因为你有一个'const'成员。 – NathanOliver

回答

2

你的类有一个const成员,而你要求std :: sort基本上可以交换你的类的实例。与包含处理对象的句柄(垃圾收集指针)的Java ArrayList不同,C++ STL容器直接包含对象本身。因此,你不能交换实例,因为那意味着覆盖一个const对象。您的解决方案必须是下列之一:如果向量拥有的,您可以使用vector<MyClass*>vector<reference_wrapper<MyClass>>,如果您有实例的其他地方,或vector<unique_ptr<MyClass>>

  • 排序指针或引用对象的矢量实例。
  • 使字段非常量。然后你的班级将有一个复制指派操作员(和一个移动ctor/op =,但只有该成员它将是相同的)
  • 提供一个自定义移动/复制操作=使用const_cast来抛弃常量场。这是一个不好的的想法,因为在某些情况下,标准说它是未定义的行为(即编译器和程序可能会设置你的计算机如果他们想要的话)。我不记得确切的标准,但你必须非常小心,不要陷入其中一个快速C++未定义的行为陷阱。
+0

我来自C背景,但我得到了Java的例子。我可以简单地删除const并将其设为private并为其实现getter,因为我希望只有一个只读的公共成员。 – user3804799

2

std::sort要求迭代器指向的元素是MoveAssignableMoveConstructible。您的课程是MoveConstructible,但它不是MoveAssignable。原因是你有一个const成员。您不能指定或从const成员移动,因为这是一个变异操作。你可以提供你自己的副本或移动赋值运算符来解决这个问题,或者让这个成员不是const。

相关问题