상위의 일부 값에 대한 참조를 보유하는 간단한 구조체를 만들려고했습니다. 부모는 벡터 내부에 unique_ptr
내에 저장됩니다. 거기로 옮기기 전에 인스턴스화됩니다. 이동 후에는 물론 참조가 더 이상 유효하지 않습니다. 나는 그들을 재현 할 수있는 방법을 찾았지만 그 해결책을 싫어한다 (아래에 나와있다). 나는 이동 생성자가 collection.push_back(std::move(d))
에서 호출되었다고 생각했지만, Derived
의 경우는 그렇지 않습니다. 그것은 unique_ptr
일지도 모르지만, 그것에 대해서는 확실하지 않습니다. 제 질문은 - 그러한 상황을 처리하는 데 선호되는 방법은 무엇입니까? 아래에서 제시 한 더 나은 솔루션이 있습니까? 이동 생성자를 무시하면 unique_ptr
도움이 될까요? 이것은 좋은 생각입니까? 또는 아래 제시된 방식으로 객체를 설계하는 것이 좋습니다.unique_ptr의 생성자 및 벡터 이동
#include <iostream>
#include <vector>
#include <memory>
// Inner object of every Base instance, is used to keep reference to
// Base's inner variables
struct Ref {
Ref(double &x, double &y)
: x(x)
, y(y)
{
}
std::reference_wrapper<double> x;
std::reference_wrapper<double> y;
};
struct Point {
double x;
double y;
};
struct Base {
virtual ~Base() { }
// every derived class uses this vector
std::vector<Ref> refs;
// some meaningless pure virtual method, ignore it
virtual void draw() = 0;
};
struct Derived : public Base {
Derived() {
std::cout << "Derived constructed" << std::endl;
}
// Method for adding point and relating it with
// a reference in refs vector
void add(double x, double y) {
points.push_back({x, y});
refs.push_back({points.back().x, points.back().y});
}
// some meaningless pure virtual method, ignore it
virtual void draw() override { }
// this vector is specific to this particular derived class
std::vector<Point> points;
};
int main() {
// some vector for storing objects
std::vector<std::unique_ptr<Base>> collection;
{
auto d = std::unique_ptr<Derived>(new Derived());
d->add(0.01, 0.02);
d->add(1.111, 2.222);
d->add(14.3333, 3.1414);
collection.push_back(std::move(d));
}
// posible solution (I hate it)
{
auto d = std::unique_ptr<Derived>(new Derived());
d->add(0.01, 0.02);
d->add(1.111, 2.222);
d->add(14.3333, 3.1414);
collection.push_back(std::move(d));
auto c = dynamic_cast<Derived *>(collection.back().get());
for (int i = 0; i < c->points.size(); i++) {
c->refs[i].x = c->points[i].x;
c->refs[i].y = c->points[i].y;
}
}
// Let's take 1st vector element and cast it to Derived
{
auto d = dynamic_cast<Derived *>(collection[0].get());
std::cout << "values from points vector:" << std::endl;
// These work correctly after moving
std::cout << d->points[0].x << std::endl;
std::cout << d->points[0].y << std::endl;
std::cout << d->points[1].x << std::endl;
std::cout << d->points[1].y << std::endl;
std::cout << d->points[2].x << std::endl;
std::cout << d->points[2].y << std::endl;
std::cout << "values from refs vector:" << std::endl;
// References of course do not work anymore
std::cout << d->refs[0].x << std::endl;
std::cout << d->refs[0].y << std::endl;
std::cout << d->refs[1].x << std::endl;
std::cout << d->refs[1].y << std::endl;
std::cout << d->refs[2].x << std::endl;
std::cout << d->refs[2].y << std::endl;
}
// Let's take 2nd vector element and cast it to Derived
{
auto d = dynamic_cast<Derived *>(collection[1].get());
std::cout << "values from points vector:" << std::endl;
// These work correctly after moving
std::cout << d->points[0].x << std::endl;
std::cout << d->points[0].y << std::endl;
std::cout << d->points[1].x << std::endl;
std::cout << d->points[1].y << std::endl;
std::cout << d->points[2].x << std::endl;
std::cout << d->points[2].y << std::endl;
std::cout << "values from refs vector with ugly fix:" << std::endl;
// References of course do not work anymore
std::cout << d->refs[0].x << std::endl;
std::cout << d->refs[0].y << std::endl;
std::cout << d->refs[1].x << std::endl;
std::cout << d->refs[1].y << std::endl;
std::cout << d->refs[2].x << std::endl;
std::cout << d->refs[2].y << std::endl;
}
return 0;
}
출력 :
Derived constructed
Derived constructed
values from points vector:
0.01
0.02
1.111
2.222
14.3333
3.1414
values from refs vector:
0
0.02
4.94602e-317
4.94603e-317
14.3333
3.1414
values from points vector:
0.01
0.02
1.111
2.222
14.3333
3.1414
values from refs vector with ugly fix:
0.01
0.02
1.111
2.222
14.3333
3.1414
귀하의 참조가'points.push_back ({x로 무효화지고, y});'collection.push_back (std :: move (d));'가 아닙니다. 후자는'unique_ptr'의 이동 생성자를 호출하지만 여전히 'Derived' 객체입니다. – aschepler
또한,'Base'는 가상 소멸자가 필요합니다. – aschepler
@aschepler 감사합니다! 나는 그것을 잊었다 - 추가됨. 와우, 당신은'points.push_back ({x, y});에 대해 옳았습니다. 어떻게 그리워했는지 모르겠군요, 고마워요! – solusipse