Это очень запутанный пример, который, вероятно, встречается редко, но я столкнулся с проблемами при выполнении следующих действий:
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()));
Я обнаружил, что некоторые указатели внутри объекта2 недействительны. Я хотел бы поделиться определениями SubClass1 и SubClass2, но, к сожалению, мне не разрешено делиться этим кодом.
Мой вопрос: существуют ли определенные контрольные списки, которые объект класса должно удовлетворять, чтобы предотвратить проблемы при перемещении временного объекта в новый объект, выделенный в куче?
Есть ли какие-либо способы заранее узнать, завершится ли операция перемещения из неудачно?
Первоначальная проблема возникла из-за ошибочного написания:
std::shared_ptr ptr = std::make_shared(MyClass());
при изменении всех моих экземпляров Shared_ptr на создание с помощью make_shared вместо new. В итоге я сузил проблему до необработанных указателей, std::move и временной ссылки на rvalue.
При выполнении:
std::shared_ptr ptr = std::make_shared();
все работало отлично.
Любопытно, что следующих проблем не возникло:
MyClass stack_obj{};
MyClass* ptr = new MyClass(std::move(stack_obj));
Кажется, есть что-то особенное в перемещении временного объекта в кучу?
Я также обнаружил, что если бы я изменил объект1, чтобы он стал указателем на Подкласс1, у меня тоже не было бы никаких проблем.
т.е.
class MyClass{
public:
SubClass1* object1;
SubClass2* object2;
MyClass(){ object1 = new SubClass1(); object2 = new SubClass2(object1); };
};
/*....*/
MyClass* ptr = new MyClass(std::move(MyClass())); //worked fine
Единственная проблема, которую я мог себе представить, заключалась в том, что объект 1 создавался в стеке для временного объекта MyClass(), а затем проблема возникла из-за перемещения объекта 1 из локального стек в кучу во время выделения указателя.
Для завершения, вот другие способы, с помощью которых я смог воспроизвести ту же проблему для исходного класса:
template
std::shared_ptr make_shared_test(Args&& ... args)
{
return std::shared_ptr(new MyClass(std::forward(args)...));
}
MyClass&& forward_test(MyClass&& param){
return static_cast(param);
}
/*....*/
MyClass* obj1(new MyClass(std::move(MyClass())));
std::shared_ptr obj2 = make_shared_test(MyClass());
std::shared_ptr obj3 = std::shared_ptr(new MyClass(forward_test(MyClass())));
std::shared_ptr obj4 = std::shared_ptr(new MyClass(std::move(MyClass())));
std::shared_ptr obj5(new MyClass(std::move(MyClass())));
Подробнее здесь: https://stackoverflow.com/questions/507 ... eap-alloca