我是一个相对的C ++新手,试图将现有项目从原始指针转换为使用复杂的内存管理协议,再转换为使用C ++ 11 shared_ptr
。总的来说,它非常顺利,我认为我理解shared_ptr
在移动语义,右值引用等方面是如何工作的。好东西。
然而,我遇到了一个奇怪的错误,我不明白,也不知道如何解决。先是一点背景。我有一个类层次结构,它以一个名为EidosValue
的抽象基类为根,一个名为EidosValue_Int_vector
的类是(间接)它的具体子类:
class EidosValue
class EidosValue_Int : public EidosValue
class EidosValue_Int_vector : public EidosValue_Int
我的代码通常在EidosValue
中进行交易,但有时候,特别是在创建新值时,我需要处理特定的子类。
我为这些类的shared_ptr
做了typedef,所以我有:
typedef std::shared_ptr<EidosValue> EidosValue_SP;
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
等。好的,所以现在问题的核心。我有一个函数返回它创建的EidosValue_SP
。根据函数中的逻辑,它可能会创建EidosValue
的几个不同具体子类之一。所以我做了这样的事情:
EidosValue_SP MyClass::MyMethod(...)
{
EidosValue_SP result;
if (...)
{
EidosValue_Int_vector_SP int_result_SP = make_shared<EidosValue_Int_vector>();
... do subclass-specific stuff with int_result_SP...
result.swap(int_result_SP);
}
else (...)
{
...similar logic for other subclasses...
}
...other shared logic...
return result;
}
问题出在swap()
电话上。我收到一个错误:“Non-const lvalue reference to type 'shared_ptr<EidosValue>' cannot bind to a value of unrelated type 'shared_ptr<EidosValue_Int_vector>'
”。这是令人费解的,因为EidosValue_Int_vector
不是“无关类型”,它是EidosValue的公共子类,这里的代码知道它。如果我输入result = make_shared<EidosValue_Int_vector>();
,编译器对此没有任何问题,因此它清楚地知道类型是相关的和兼容的。出于某种原因,它只是在swap()
的上下文中不喜欢它。在我的项目的其他地方,我能够简单地做一个return int_result_SP;
,声明返回类型为EidosValue_SP,并且工作正常 - 编译器很高兴在此上下文中将EidosValue_Int_vector_SP视为EidosValue_SP - 但由于函数底部的共享逻辑,我不能在这里做到这一点。
我在这里的实现有点受限制,因为这段代码是一个瓶颈,需要快速运行(是的,我知道从实际检测代码,是的,它确实很重要)。因此,必须使用make_shared
来避免双重分配,而且当我将指针从int_result_SP
移交给结果时,我也非常希望避免引用计数递增/递减;当有两个shared_ptrs指向新实例时,我不希望有时间。所以swap()
似乎是显而易见的方式;但我被这个编译器错误阻止了。为什么会发生这种情况?我该如何解决?谢谢!
附录:
哦,进一步思考这个我打赌我知道为什么错误发生了。 swap()
不反对将EidosValue_Int_vector
放入EidosValue_SP
,但确实将EidosValue
放入EidosValue_Int_vector_SP
时遇到问题}};在那个方向上,类型不兼容。我没有这样想过,因为result
没有价值(也就是说nullptr
,我猜);但当然swap()
并不知道。好的,所以如果这就是问题,那么问题仍然存在:如何在保持代码快速的同时实现转移 - 不执行refcount inc / dec而不是放弃使用make_shared
?现在我理解了这个问题(我认为),似乎有一些我忽略的API或技巧......
答案 0 :(得分:5)
你不能swap
因为,虽然EidosValue_Int_vector
是 EidosValue
,但反过来并不正确。
答案 1 :(得分:4)
这正是std::move
的用途。使用:
result = std::move (int_result_SP);