首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将临时对象移动到分配给堆的对象时可能出现的运行时问题?

将临时对象移动到分配给堆的对象时可能出现的运行时问题?
EN

Stack Overflow用户
提问于 2018-06-08 06:44:39
回答 1查看 55关注 0票数 0

这是一个非常复杂的例子,可能很少见,但我在执行以下操作时遇到了问题:

代码语言:javascript
复制
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的定义,但不幸的是,我不允许共享这段代码。

我的问题是,当将临时对象移动到新的已分配堆对象时,是否存在类对象必须满足的某些检查列表以防止出现问题?是否有任何方法可以在手前知道移动操作是否会失败?

最初的问题是由于错误地写成:

代码语言:javascript
复制
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>(MyClass());

当更改所有要通过make_shared而不是new构建的make_shared实例时。最后,我将问题缩小到原始指针、std::move和一个临时rvalue引用。

在做时:

代码语言:javascript
复制
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();

一切都很好。

奇怪的是,下列方面没有任何问题:

代码语言:javascript
复制
MyClass stack_obj{};
MyClass* ptr = new MyClass(std::move(stack_obj));

它似乎是特定于将临时对象移到堆中的东西吗?

我还发现,如果我将object1改为SubClass1指针,我也没有任何问题。即

代码语言:javascript
复制
class MyClass{
public:
SubClass1* object1;
SubClass2* object2; 
MyClass(){ object1 = new SubClass1(); object2 = new SubClass2(object1); };
};
/*....*/
MyClass* ptr = new MyClass(std::move(MyClass())); //worked fine

我能想象到的唯一问题是,在堆栈上为临时对象MyClass()创建了MyClass,然后在指针分配期间将object1从本地堆栈移动到堆。

为了完成任务,我还可以通过以下其他方式为原始类复制相同的问题:

代码语言:javascript
复制
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())));
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-08 13:13:36

问题是我忘记了SubClass1上的move构造函数(规则5)。因此,编译器实际上会复制类而不是移动类,一旦为SubClass1调用了析构函数,它就会切断object1和object2之间的关系,从而导致未定义的行为。

谢谢你的时间,很抱歉浪费了你的时间!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50754869

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档