我可以在C++Actor框架中使用C++11智能指针作为消息返回类型吗

Can I use C++11 smart pointers as a message return type in the C++ Actor Framework?

本文关键字:指针 消息 返回类型 智能 C++11 C++Actor 框架 我可以      更新时间:2023-10-16

当我使用unique_ptr作为返回类型时,我收到编译器错误C2280:

'caf::detail::tuple_vals<std::unique_ptr<A,std::default_delete<_Ty>>>::tuple_vals(const caf::detail::tuple_vals<std::unique_ptr<_Ty,std::default_delete<_Ty>>> &)': attempting to reference a deleted function  includecafdetailtuple_vals.hpp   102

以下是一些说明问题的示例代码(从C++Actor Framework的一个示例中修改而来):

#include <iostream>
#include "caf/all.hpp"
using namespace caf;
using namespace std;
class A
{
public:
    int a;
    A(int a)
    {
        this->a = a;
    }
};
using a_type = typed_actor<replies_to<int>::with<unique_ptr<A>>>;
a_type::behavior_type a_behavior(a_type::pointer self)
{
    return
    {
        [self](const int& a) -> unique_ptr<A>
        {
            return make_unique<A>(5);
        }
    };
}
void tester(event_based_actor* self, const a_type& testee)
{
    self->link_to(testee);
    // will be invoked if we receive an unexpected response message
    self->on_sync_failure(
        [=]
        {
            aout(self) << "AUT (actor under test) failed" << endl;
            self->quit(exit_reason::user_shutdown);
        });
    self->sync_send(testee, 5).then(
        [=](unique_ptr<A> a)
        {
            if(a->a == 5)
            {
                aout(self) << "AUT success" << endl;
            }
            self->send_exit(testee, exit_reason::user_shutdown);
        }
    );
}

CAF要求消息中的每个类型都是常规。这意味着它必须提供std::unique_ptr没有的复制构造函数。因此编译器会抱怨。

消息具有写时复制实现。您可以廉价地复制一条消息,因为它只会在内部增加引用计数。在任何时候,您都可以执行消息元素的常量访问。只有当消息的引用计数大于1并且您请求非常量访问时,写时复制的"写"部分才会生效。此时,运行时调用所包含类型的复制构造函数来创建新消息。

如果CAF无条件地执行此复制,而与引用计数无关,那么就不可能有效地支持数据流编程,在数据流编程中,参与者接收消息,修改其内容,并转发到下一阶段。

将消息视为指针容器:包含的元素在空闲存储中分配。在消息中存储指针通常是一个设计缺陷。双重包装也对分配器造成了不必要的压力。

由于您可以灵活地对消息进行切片,因此可以创建单个消息,然后在各种上下文中使用包含的值。

是的,C++Actor框架确实允许在返回消息中使用智能指针,但不允许使用unique_ptr的形式。

C++Actor Framework实现当前生成消息的副本并取消引用unique_ptr,从而导致编译器错误。

不要使用unique_ptr,而是使用shared_ptr。修改问题的示例代码时,引用计数将为2。我还使用了一个自定义的删除函数来验证内存是否按预期释放,尽管创建了第二个share_ptr