尝试执行 shared_ptr swap() 时出现奇怪错误
Strange error trying to do a shared_ptr swap()
我是一个相对的 C++ 新手,试图将现有项目从原始指针转换为使用 C++11 的 shared_ptr
,使用复杂的内存管理协议。总的来说,进展非常顺利,我 认为 我理解 shared_ptr
在移动语义、右值引用等方面的工作原理。好东西。
但是,我遇到了一个奇怪的错误,我不明白也不知道如何修复。先介绍一点背景。我有一个 class 层次结构植根于一个名为 EidosValue
的抽象基础 class,而一个名为 EidosValue_Int_vector
的 class 是(间接地)一个具体的子 class 其中:
class EidosValue
class EidosValue_Int : public EidosValue
class EidosValue_Int_vector : public EidosValue_Int
我的代码一般在EidosValue
中进行流量,但有时,尤其是在创建新值时,我需要处理特定的子class。
我已经为这些 class 的 shared_ptr
完成了类型定义,所以我有:
typedef std::shared_ptr<EidosValue> EidosValue_SP;
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
等等。好的,现在进入问题的核心。我有一个 return 是它创建的 EidosValue_SP
的函数。根据函数内的逻辑,它可能会创建 EidosValue
的几个不同的具体子 class 之一。所以我做了这样的事情:
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
不是 "unrelated type",它是 EidosValue 的 public subclass,这里的代码知道这一点。如果我键入 result = make_shared<EidosValue_Int_vector>();
编译器对此没有任何问题,因此它清楚地知道这些类型是相关且兼容的。出于某种原因,它只是不喜欢 swap()
的上下文。在我项目的其他地方,我已经能够简单地做一个 return int_result_SP;
,声明的 return 类型为 EidosValue_SP,而且效果很好——编译器很乐意考虑一个 EidosValue_Int_vector_SP 成为那个上下文中的 EidosValue_SP – 但我不能在这里这样做,因为函数底部的共享逻辑。
我在这里的实现有些受限,因为这段代码是一个瓶颈,需要 运行 快速(是的,我从实际检测代码中知道这一点,是的,它确实很重要)。所以必须使用 make_shared
来避免双重分配,而且当我将指针从 int_result_SP
传递给结果时,我也强烈希望避免引用计数 increment/decrement ;我不希望有两个 shared_ptrs 指向新实例的时刻。所以 swap()
似乎是显而易见的方法;但我被这个编译器错误阻止了。为什么会这样,我该如何解决?谢谢!
附录:
哦,仔细想想我打赌我知道为什么会发生错误。 swap()
不反对将EidosValue_Int_vector
放入EidosValue_SP
,但确实将EidosValue
放入EidosValue_Int_vector_SP
;在那个方向上,类型不兼容。我没有那样想过,因为 result
没有价值(我猜是 nullptr
);但当然 swap()
不知道。好的,如果那是问题所在,那么问题仍然存在:我如何在保持代码快速的同时实现传输——不进行引用计数 inc/dec 并且不放弃使用 make_shared
?现在我明白了这个问题(我认为)似乎有一些 API 或技巧被我忽略了......
你不能swap
因为,虽然EidosValue_Int_vector
是EidosValue
,但反过来并不成立。
这正是 std::move
的用途。使用:
result = std::move (int_result_SP);
我是一个相对的 C++ 新手,试图将现有项目从原始指针转换为使用 C++11 的 shared_ptr
,使用复杂的内存管理协议。总的来说,进展非常顺利,我 认为 我理解 shared_ptr
在移动语义、右值引用等方面的工作原理。好东西。
但是,我遇到了一个奇怪的错误,我不明白也不知道如何修复。先介绍一点背景。我有一个 class 层次结构植根于一个名为 EidosValue
的抽象基础 class,而一个名为 EidosValue_Int_vector
的 class 是(间接地)一个具体的子 class 其中:
class EidosValue
class EidosValue_Int : public EidosValue
class EidosValue_Int_vector : public EidosValue_Int
我的代码一般在EidosValue
中进行流量,但有时,尤其是在创建新值时,我需要处理特定的子class。
我已经为这些 class 的 shared_ptr
完成了类型定义,所以我有:
typedef std::shared_ptr<EidosValue> EidosValue_SP;
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
等等。好的,现在进入问题的核心。我有一个 return 是它创建的 EidosValue_SP
的函数。根据函数内的逻辑,它可能会创建 EidosValue
的几个不同的具体子 class 之一。所以我做了这样的事情:
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
不是 "unrelated type",它是 EidosValue 的 public subclass,这里的代码知道这一点。如果我键入 result = make_shared<EidosValue_Int_vector>();
编译器对此没有任何问题,因此它清楚地知道这些类型是相关且兼容的。出于某种原因,它只是不喜欢 swap()
的上下文。在我项目的其他地方,我已经能够简单地做一个 return int_result_SP;
,声明的 return 类型为 EidosValue_SP,而且效果很好——编译器很乐意考虑一个 EidosValue_Int_vector_SP 成为那个上下文中的 EidosValue_SP – 但我不能在这里这样做,因为函数底部的共享逻辑。
我在这里的实现有些受限,因为这段代码是一个瓶颈,需要 运行 快速(是的,我从实际检测代码中知道这一点,是的,它确实很重要)。所以必须使用 make_shared
来避免双重分配,而且当我将指针从 int_result_SP
传递给结果时,我也强烈希望避免引用计数 increment/decrement ;我不希望有两个 shared_ptrs 指向新实例的时刻。所以 swap()
似乎是显而易见的方法;但我被这个编译器错误阻止了。为什么会这样,我该如何解决?谢谢!
附录:
哦,仔细想想我打赌我知道为什么会发生错误。 swap()
不反对将EidosValue_Int_vector
放入EidosValue_SP
,但确实将EidosValue
放入EidosValue_Int_vector_SP
;在那个方向上,类型不兼容。我没有那样想过,因为 result
没有价值(我猜是 nullptr
);但当然 swap()
不知道。好的,如果那是问题所在,那么问题仍然存在:我如何在保持代码快速的同时实现传输——不进行引用计数 inc/dec 并且不放弃使用 make_shared
?现在我明白了这个问题(我认为)似乎有一些 API 或技巧被我忽略了......
你不能swap
因为,虽然EidosValue_Int_vector
是EidosValue
,但反过来并不成立。
这正是 std::move
的用途。使用:
result = std::move (int_result_SP);