Это очень запутанный пример, который, вероятно, встречается редко, но я столкнулся с проблемами при выполнении следующих действий:
class MyClass{
public:
SubClass1 object1; //has pointers/smart-pointers to objects that have pointers to SubClass2
SubClass2* object2; //has pointers/smart-pointers to objects that have pointers/smart-pointers to SubClass1
MyClass(){ object2 = new SubClass2(&object1); }; //SubClass2 constructor establishes the relationship between object1 and object2 pointed-to-objects.
};
/*....*/
MyClass* ptr = new MyClass(std::move(MyClass()));
Я обнаружил, что некоторые указатели внутри object2 были недействительными.Я хотел бы поделиться определениями SubClass1 и SubClass2, но, к сожалению, мне не разрешено делиться этим кодом.
Мой вопрос: существуют ли определенные контрольные списки, которым должен удовлетворять объект класса, чтобы предотвратить проблемы при перемещениивременный объект для новой выделенной кучи объекта?Есть ли какие-либо способы узнать заранее, не удастся ли выполнить операцию перемещения?
Первоначальная проблема возникла из-за ошибочной записи:
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>(MyClass());
при изменении всех моих экземпляров shared_ptr, которые будут построены черезmake_shared вместо new.Я сузил проблему до необработанных указателей, std :: move и временной ссылки на rvalue.
При выполнении:
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
все работало идеально.
Любопытно, что следующие проблемы не возникли:
MyClass stack_obj{};
MyClass* ptr = new MyClass(std::move(stack_obj));
Кажется, что-то особенное для перемещения временного объекта в кучу?
Я также узнал, что если я вместо объекта object1 заменюбыть указателем SubClass1, у меня также не было никаких проблем.то есть
class MyClass{
public:
SubClass1* object1;
SubClass2* object2;
MyClass(){ object1 = new SubClass1(); object2 = new SubClass2(object1); };
};
/*....*/
MyClass* ptr = new MyClass(std::move(MyClass())); //worked fine
Единственная проблема, которую я мог себе представить, была в том, что object1 был создан в стеке для временного объекта MyClass (), а затем возникла проблема с перемещением object1 из локального стека в кучу во времявыделение указателя.
В завершение, есть и другие способы, с помощью которых я смог повторить ту же проблему для исходного класса:
template <class... Args>
std::shared_ptr<MyClass> make_shared_test(Args&& ... args)
{
return std::shared_ptr<MyClass>(new MyClass(std::forward<Args>(args)...));
}
MyClass&& forward_test(MyClass&& param){
return static_cast<MyClass&&>(param);
}
/*....*/
MyClass* obj1(new MyClass(std::move(MyClass())));
std::shared_ptr<MyClass> obj2 = make_shared_test(MyClass());
std::shared_ptr<MyClass> obj3 = std::shared_ptr<MyClass>(new MyClass(forward_test(MyClass())));
std::shared_ptr<MyClass> obj4 = std::shared_ptr<MyClass>(new MyClass(std::move(MyClass())));
std::shared_ptr<MyClass> obj5(new MyClass(std::move(MyClass())));