[英]Error when using set_union and set_intersection
我有兩個集合,我正在嘗試進行並集(進行相交時會遇到相同的錯誤)。 這是錯誤:
error C3892: 'std::_Tree_const_iterator<_Mytree>::operator *' : you cannot assign to a variable that is const
代碼段(如果我用->注釋掉這一行,則代碼會編譯,而我做聯合工作的方法也可以正常工作):
set<Line *>::iterator it;
set<Line *> * newSet = new set<Line *>();
leftLines = pLeft->getSet();
rightLines = pRight->getSet();
-->it = set_union(leftLines->begin(),leftLines->end(),rightLines->begin(), rightLines->end(), newSet->begin());
for(it = leftLines->begin(); it != leftLines->end(); it++)
{
newSet->insert(*it);
}
for(it = rightLines->begin(); it != rightLines->end(); it++)
{
newSet->insert(*it);
}
it = newSet->begin();
while(it != newSet->end())
{
result->insert(*it);
it++;
}
我敢肯定這有點愚蠢,但我有點迷茫。 我認為該代碼段就足夠了,但是我可以提供所需的任何內容。 謝謝。
這是C ++,不是Java [edit:或.NET]。 您幾乎肯定要替換(例如):
set<Line *> * newSet = new set<Line *>();
只是:
set<Line *> newSet;
...或者,更好的是,可能只是:
set<Line> newSet;
盡管根據您發布的代碼無法確定某些內容,但您的left
right
也很可能也不應該處理指針-如果它們要執行某種操作,則是一個參考可能更有意義(不過,正如我所說,僅基於您發布的內容,無法確定地說)。
完成此操作后,您將遇到一個小問題: set
(或multiset
, map
或multimap
)上的“常規”迭代器實際上是const_iterator。 將某些內容插入關聯容器后,您將無法對其進行更改,因為這可能會破壞集合的不變性(進行排序)。 如果要更改現有項目,則需要從包含中刪除,進行更改,然后將更改的對象重新插入容器。 在您的情況下,您只是插入新項目,因此需要insert_iterator
。
由於您不打算修改left
或right
,因此最好將它們也視為const
:
std::set_union(left.cbegin(), left.cend(),
right.cbegin(), right.cend(),
std::inserter(newSet, newSet.end()));
如果決定自己模擬set_union,則可以執行以下操作:
std::set<Line> newSet(left.cbegin(), left.cend());
std::copy(right.cbegin(), right.cend(), std::inserter(newSet, newSet.end()));
編輯:
通常,您不希望將遍歷器傳遞給容器,而不是傳遞指向容器的指針。 例如,要打印出內容,您現在顯然具有以下內容:
void print_data(std::vector<Line *> const *data) {
for (int i=0; i<data->size(); i++)
std::cout << *(*data)[i] << "\n";
}
它可能具有更多的格式等信息,但是目前我們將忽略這些細節,並假設它是如此簡單。 要直接從您選擇的容器中寫入數據,通常需要一個模板,該模板將接受任意類型的迭代器:
template <class inIt>
void print_data(inIt begin, inIt end) {
while (begin != end)
std::cout << *begin++ << '\n';
}
但是,我們可以更進一步,並將輸出指定為迭代器:
template <class inIt, class outIt>
void print_data(inIt begin, inIt end, outIt dest) {
while (begin != end) {
*dest++ = *begin++;
*dest++ = '\n';
}
}
您可以再走一步,並允許用戶指定要在項目之間使用的分隔符,而不是始終使用'\\ n',但是到那時,您只需要復制標准庫中已經存在的內容- std::copy
和std::ostream_iterator
,這實際上可能是您要處理的方式:
std::copy(newSet.begin(), newSet.end(),
std::ostream_iterator<Line>(std::cout, "\n"));
但是請注意,就標准庫而言, ostream_iterator
只是另一個迭代器。 如果您只是要打印出left
和right
並集,則可以跳過甚至創建一個集合來保存該並集,而直接將其打印出來:
std::set_union(left.cbegin(), left.cend(),
right.cbegin(), right.cend(),
std::ostream_iterator<Line>(std::cout, "\n"));
ostream_iterator
寫入文件而不是將其放入普通集合的事實與標准庫完全無關。 它具有一些迭代器類,並且可以將輸出寫入建模正確類的任何迭代器。
現在,可以說,我可能正在大步向前-可能需要在將數據寫入控制台之前對數據進行其他處理。 我的意思不是說您必須將聯合直接寫入標准輸出,而是在打印出來之前不必將其寫入其他集合。
set迭代器不是輸出迭代器。 用這個:
set_union(leftLines->begin(),leftLines->end(),rightLines->begin(), rightLines->end(), inserter(*newSet, newSet->begin()));
另外,為什么要填充newSet
? 在並集/相交之后保持原樣,否則並集/相交將毫無意義。
set<Line *>::iterator it;
set<Line *> newSet; // No need to `new` this
leftLines = pLeft->getSet();
rightLines = pRight->getSet();
set_union(leftLines->begin(),leftLines->end(),rightLines->begin(), rightLines->end(), inserter(newSet, newSet.begin()));
// Assuming you really need the below code - you could likely just make an inserter directly on `result` instead of the copying.
it = newSet.begin();
while(it != newSet.end())
{
result->insert(*it);
it++;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.