如何 push_back 一个 "unique_ptr<Base>&" 到 "vector<unique_ptr<Derived>>"
How to push_back a "unique_ptr<Base>&" to "vector<unique_ptr<Derived>>"
我需要通过一些条件检查在 2 vector<unique_ptr>
之间移动元素。移动后,我将忽略from-vector(将所有权转移到to-vector)。
案例 1:从 vector<unique_ptr<Derived>> fromDeriveds
移动到 vector<unique_ptr<Base>> toBases
:
vector<unique_ptr<Derived>> fromDeriveds;
vector<unique_ptr<Base>> toBases;
for (unique_ptr<Derived> &derived: fromDeriveds)
{
if (derived->prop == 1)
{
toBases.push_back(move(derived));
}
}
这个案例不错
情况 2:从 vector<unique_ptr<Base>> fromBases
移动到 vector<unique_ptr<Derived>> toDeriveds
:
vector<unique_ptr<Base>> fromBases;
vector<unique_ptr<Derived>> toDeriveds;
for (unique_ptr<Base> &base: fromBases)
{
Derived *derived = dynamic_cast<Derived *>(base.get());
if (derived && derived->prop == 1)
{
toDeriveds.push_back(move(base));
}
}
编译失败,出现以下错误:
main.cpp:44:44: error: no matching function for call to ‘std::vector<std::unique_ptr<Derived> >::push_back(std::remove_reference<std::unique_ptr<Base>&>::type)’
toDeriveds.push_back(move(base));
^
虽然我可以通过下面的方式来完成,但它是复制而不是移动:
vector<unique_ptr<Base>> fromBases;
vector<unique_ptr<Derived>> toDeriveds;
for (unique_ptr<Base> &base: fromBases)
{
Derived *derived = dynamic_cast<Derived *>(base.get());
if (derived && derived->prop == 1)
{
toDeriveds.push_back(make_unique<Derived>(*derived));
}
}
有没有更好的方法来实现目标?
您可以迭代 fromBase
列表并进行检查,如果满足该要求,那么您可以简单地 release
指针 - 它会在不调用析构函数的情况下放弃基指针。只要确保删除已释放的空指针,以防您需要再次使用 fromBase
向量。
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
using namespace std;
class Base{ public: virtual ~Base() = default; };
class Derived: public Base {};
int main() {
vector<unique_ptr<Base>> fromBase;
vector<unique_ptr<Derived>> toDerived;
fromBase.emplace_back(make_unique<Base>());
fromBase.emplace_back(make_unique<Base>());
fromBase.emplace_back(make_unique<Derived>());
for(auto& p: fromBase) {
Derived* d = dynamic_cast<Derived *>(p.get());
// make other checks here
if(d != nullptr) {
toDerived.emplace_back(d);
p.release();
}
}
// make sure to remove released pointers
fromBase.erase(remove_if(fromBase.begin(), fromBase.end(), [](const auto& p) { return !p; }), fromBase.end());
cout << fromBase.size() << " " << toDerived.size() << endl;
}
我需要通过一些条件检查在 2 vector<unique_ptr>
之间移动元素。移动后,我将忽略from-vector(将所有权转移到to-vector)。
案例 1:从 vector<unique_ptr<Derived>> fromDeriveds
移动到 vector<unique_ptr<Base>> toBases
:
vector<unique_ptr<Derived>> fromDeriveds;
vector<unique_ptr<Base>> toBases;
for (unique_ptr<Derived> &derived: fromDeriveds)
{
if (derived->prop == 1)
{
toBases.push_back(move(derived));
}
}
这个案例不错
情况 2:从 vector<unique_ptr<Base>> fromBases
移动到 vector<unique_ptr<Derived>> toDeriveds
:
vector<unique_ptr<Base>> fromBases;
vector<unique_ptr<Derived>> toDeriveds;
for (unique_ptr<Base> &base: fromBases)
{
Derived *derived = dynamic_cast<Derived *>(base.get());
if (derived && derived->prop == 1)
{
toDeriveds.push_back(move(base));
}
}
编译失败,出现以下错误:
main.cpp:44:44: error: no matching function for call to ‘std::vector<std::unique_ptr<Derived> >::push_back(std::remove_reference<std::unique_ptr<Base>&>::type)’
toDeriveds.push_back(move(base));
^
虽然我可以通过下面的方式来完成,但它是复制而不是移动:
vector<unique_ptr<Base>> fromBases;
vector<unique_ptr<Derived>> toDeriveds;
for (unique_ptr<Base> &base: fromBases)
{
Derived *derived = dynamic_cast<Derived *>(base.get());
if (derived && derived->prop == 1)
{
toDeriveds.push_back(make_unique<Derived>(*derived));
}
}
有没有更好的方法来实现目标?
您可以迭代 fromBase
列表并进行检查,如果满足该要求,那么您可以简单地 release
指针 - 它会在不调用析构函数的情况下放弃基指针。只要确保删除已释放的空指针,以防您需要再次使用 fromBase
向量。
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
using namespace std;
class Base{ public: virtual ~Base() = default; };
class Derived: public Base {};
int main() {
vector<unique_ptr<Base>> fromBase;
vector<unique_ptr<Derived>> toDerived;
fromBase.emplace_back(make_unique<Base>());
fromBase.emplace_back(make_unique<Base>());
fromBase.emplace_back(make_unique<Derived>());
for(auto& p: fromBase) {
Derived* d = dynamic_cast<Derived *>(p.get());
// make other checks here
if(d != nullptr) {
toDerived.emplace_back(d);
p.release();
}
}
// make sure to remove released pointers
fromBase.erase(remove_if(fromBase.begin(), fromBase.end(), [](const auto& p) { return !p; }), fromBase.end());
cout << fromBase.size() << " " << toDerived.size() << endl;
}