5

我是一个相对的 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为这些类的 s 做了 typedefs,所以我有:

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,但将放入中确实有问题 在那个方向上,类型不兼容。我没有这样想过,因为它没有任何价值(我猜是有);但当然不知道。好的,所以如果这是问题所在,那么问题仍然存在:如何在保持代码快速的同时实现传输——不执行 refcount inc/dec 并且不离开 using ?既然我理解了这个问题(我认为),似乎可能只是我忽略了一些 API 或技巧......EidosValueEidosValue_Int_vector_SPresultnullptrswap()make_shared

4

2 回答 2

5

你不能swap因为,虽然EidosValue_Int_vector EidosValue相反的,但不是真的。

于 2015-09-23T16:48:02.483 回答
4

这正是std::move它的用途。利用:

    result = std::move (int_result_SP);
于 2015-09-23T17:23:09.173 回答