2017-03-07 82 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。