8

だから私は次のようなベクトルを持っています:

std::vector<std::unique_ptr<SomeClass>> myVector;

次に、の生のポインターを含む別のベクトルがありますSomeClass

std::vector<SomeClass*> myOtherVector;

内部に要素があれば内部myOtherVectorにもあるので、各要素を調べてから同じ要素を削除しmyVectorたいと思います。次に、ベクトルをクリアします。これは私が思いついたものです:myOtherVectormyVector

for(size_t i = 0; i < myOtherVector.size(); i++)
{
    myVector.erase(std::remove(myVector.begin(), myVector.end(), myOtherVector[i]), myVector.end());
}
myOtherVector.clear();

myVectorこれは、一意のポインターを保持しているため、コンパイル時エラーを生成しますが、remove()関数に生のポインターを与えています。この問題を解決する適切な方法がわからないため、ここで助けが必要です。行を次のように変更しました。

myVector.erase(std::remove(myVector.begin(), myVector.end(), std::unique_ptr<SomeClass>(myOtherVector[i])), myVector.end());

std::unique_ptr2 つの s が同じオブジェクトを参照しているため、これらすべての最初の部分は正しくありません。内部の要素にmyVectorは参照が含まれており、上記の行の一意のポインターの構築は別の参照です。そして、同じ型を取得するために新しいポインターを構築することが概念的にこれを行うための正しい方法であるかどうかさえわかりません。そこで、一意のポインターを共有ポインターに変更しました。

std::vector<std::shared_ptr<SomeClass>> myVector;
std::vector<SomeClass*> myOtherVector;

for(size_t i = 0; i < myOtherVector.size(); i++)
{
    myVector.erase(std::remove(myVector.begin(), myVector.end(), std::shared_ptr<SomeClass>(myOtherVector[i])), myVector.end());
}
myOtherVector.clear();

アプリケーションをmyVector.erase()実行すると、「ApplicationName.exe がブレークポイントをトリガーしました」というランタイム エラーが発生しました。[続行] をクリックすると、デバッグ アサーション エラーが発生しました。

明らかに私は何か間違ったことをしているのですが、何が悪いのかわかりません。生のポインターを使用してベクトルからスマートポインターを消去する正しい方法は何ですか?

4

3 に答える 3

3

std::unique_ptrgetには、所有されたポインターを返すメンバー関数があります。

次の点を考慮してください。

std::sort(myOtherVector.begin(), myOtherVector.end());

myVector.erase(std::remove_if(myVector.begin(), myVector.end(),
[&](std::unique_ptr<SomeClass> const& p) -> bool
{
    return std::binary_search(myOtherVector.begin(), myOtherVector.end(),
                              p.get());
}));

myOtherVector.clear();    
于 2013-02-28T01:13:05.013 に答える
3

これは私がそれを行う方法です。パフォーマンスは改善される可能性がありますが、それがアプリケーションのボトルネックにならない限り、私は気にしません。アルゴリズムは単純明快です。

これは、最初のコンテナー ( ) から、2 番目のコンテナー (myOtherVector) の要素によってポイントされるオブジェクトをポイントするすべての要素remove_ifを選択的に削除するために使用されます。myVector次に、2 番目のコンテナーをクリアします。述語は、ラムダ関数を介して実装されます。

#include <vector>
#include <memory>
#include <algorithm>

struct SomeClass { /* ... */ };

int main()
{
    std::vector<std::unique_ptr<SomeClass>> myVector;
    std::vector<SomeClass*> myOtherVector;

    myVector.erase(
        std::remove_if( // Selectively remove elements in the second vector...
            myVector.begin(),
            myVector.end(),
            [&] (std::unique_ptr<SomeClass> const& p)
            {   // This predicate checks whether the element is contained
                // in the second vector of pointers to be removed...
                return std::find(
                    myOtherVector.cbegin(), 
                    myOtherVector.cend(), 
                    p.get()
                    ) != myOtherVector.end();
            }),
        myVector.end()
        );

    myOtherVector.clear();
}
于 2013-02-28T01:13:29.840 に答える