zze*_*man 3 c++ vector unique-ptr visual-studio-2012
我正在使用Visual Studio 2012 C++,我想设置两个具有彼此相同的唯一指针的向量.
using namespace std;
vector<unique_ptr<Unit>> unitVector;
vector<unique_ptr<Unit>> nonDeadUnits;
.... (stuff added to unitVector) ....
for (auto unit = unitVector.begin(); unit != unitVector.end(); ++unit) {
if ((*unit)->health > 0) {
nonDeadUnits.push_back(*unit);
}
}
unitVector.clear();
unitVector = nonDeadUnits; // error here (see below error code)
Run Code Online (Sandbox Code Playgroud)
我想删除所有生命值小于0的单位,但是如果我尝试直接从向量中删除它们,我会尝试访问我不应该访问的内存,从而终止程序.这就是为什么我选择这样做的原因.唯一的问题是unique_ptr不允许我想要的复制类型.这是错误:
error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility 2089
Run Code Online (Sandbox Code Playgroud)
我想有unique_ptr,因为向量在稍后的for循环中调用子类方法,它有助于覆盖.那么如何将矢量设置为彼此相等或者有更好的方法呢?
一般的想法是使用std::remove_if交换元素unitsVector,然后一旦所有死单位都在向量的末尾,你只需将它们切掉.
#include <memory>
#include <vector>
struct Unit {
int health;
};
// The non-working version.
//
// void remove_dead_units(std::vector<std::unique_ptr<Unit>> &unitVector)
// {
// std::vector<std::unique_ptr<Unit>> nonDeadUnits;
// for (auto unit : unitVector)
// if (unit->health > 0)
// nonDeadUnits.push_back(unit);
// unitVector = nonDeadUnits;
// }
void remove_dead_units(std::vector<std::unique_ptr<Unit>> &unitVector)
{
auto isDead = [](const std::unique_ptr<Unit> &u) -> bool { return (u->health <= 0); };
auto newEnd = std::remove_if(unitVector.begin(), unitVector.end(), isDead);
unitVector.erase(newEnd, unitVector.end());
}
Run Code Online (Sandbox Code Playgroud)
我确信还有其他方法可以做到这一点,更接近于你所尝试的内容(编辑:实际上KerrekSB刚刚发布了一个,只使用了一个std::move和一个swap); 但我认为"shuffle and chop"方法更现代--C++ ish.
也许以下逻辑会更简单:
vector<unique_ptr<Unit>> unitVector = /* ... */;
vector<unique_ptr<Unit>> nonDeadUnits;
for (auto & p : unitvector)
{
if (p->health > 0) { nonDeadUnits.push_back(std::move(p)); }
}
unitVector.swap(nonDeadUnits);
Run Code Online (Sandbox Code Playgroud)
否则,标准的删除 - 删除习惯可能更多是主流:
unitVector.erase(remove_if(unitVector.begin(), unitVector.end(),
[](unique_ptr<Unit> const & p) -> bool { return p->health <= 0; }),
unitVector.end());
Run Code Online (Sandbox Code Playgroud)