C++ 协议缓冲区是否支持移动构造函数
我已经检查了规格和来源,但没有找到 如果没有,有人知道要添加它的计划吗C++ 协议缓冲区是否支持移动构造函数,c++,protocol-buffers,protobuf-c,C++,Protocol Buffers,Protobuf C,我已经检查了规格和来源,但没有找到 如果没有,有人知道要添加它的计划吗 我使用的是原文件> /COD>语法,编写一个库,考虑在返回值与UNIQuYGPTR之间的关系。< P> > 2.2.1版,C++原生成器编译器只生成复制构造函数和拷贝赋值操作符。但是,如果编译器支持(并且满足其条件),那么无论如何都不会调用复制构造函数 您可以将一些打印语句添加到消息副本构造函数的生成代码中,以查看它们是否真的被调用。您还可以通过编写protoc插件来实现这一点,因此它在protoc调用之间保持不变 如果您尝
我使用的是<>原文件> /COD>语法,编写一个库,考虑在返回值与UNIQuYGPTR之间的关系。< P> > 2.2.1版,C++原生成器编译器只生成复制构造函数和拷贝赋值操作符。但是,如果编译器支持(并且满足其条件),那么无论如何都不会调用复制构造函数 您可以将一些打印语句添加到消息副本构造函数的生成代码中,以查看它们是否真的被调用。您还可以通过编写protoc插件来实现这一点,因此它在protoc调用之间保持不变
// RVO will bring the return value to a without using copy constructor.
SomeMessage a = SomeFooWithMessageReturned();
std::move
将左值移动到列表/子消息等中,请尝试使用ConcreteMessage::Swap
方法。交换的项目将是无用的
// Non-copy usage.
somemessage.add_somerepeated_message()->Swap(&a);
somemessage.mutable_somesinglar_message()->Swap(&a);
// With message copying
somemessage.add_somerepeated_message()->CopyFrom(a);
*somemessage.mutable_somesinglar_message() = a;
根据这一点,Protobuf版本3.4.0将支持RVO。事实上,很难确保RVO在您期望的所有情况下都使用,因为编译器不需要使用它,而且编译器在决定是否可以使用它时并不总是非常聪明。基本上,您必须确保您的函数只有一个return语句(返回局部变量)。此外,在实践中还有许多其他情况需要类似于移动的语义,但仔细使用swap()可以涵盖其中一些情况。显然,如果需要类似于大型消息对象向量的内容,RVO将帮不上忙。一种解决方法是使用消息的unique_ptr向量,但这是一种符号麻烦,它意味着源函数必须返回unique_ptr以避免复制到其他地方,因此这种解决方法可能会感染大量代码。@JimOldfield而不是
std::vector
,您可以使用protobuf容器google::protobuf::RepeatedPtrField
。这个类用于重复的字段,但也可以用于其他目的。它在内部使用指针,但迭代器直接指向消息,因此不需要双重取消引用。根据Daniel Schepler的回答,从protobuf 3.4开始,这两种解决方案都是不必要的。3.6.1的备注与protobuf changlelog不同,后者在3.4中为大多数对象添加了移动,在3.5中增加了一些(数组类型),并在3.6中关闭了CXX功能的防护,特别是,3.4具有“当C++11可用时,将引入以下C++11功能“:-消息中引入了移动构造函数和移动分配-重复字段构造函数现在采用std::initializer_列表当这是时,有人附加了一个他们为添加移动构造函数支持而编写的protoc生成器插件。他们称之为protoc-gen-cxx11,但不幸的是我在任何地方都找不到它。非常感谢您注意到Swap
方法。可以使用下一个函数模拟protobuf对象的移动分配:template static void pb_Move_assign(protobuf&to,protobuf&from){from.Swap(&to);from.Clear();}
@anton_rh Clear()不是必需的;无法保证在移动后来自对象的将处于什么状态(除非它是合法状态),例如,短std::字符串在移动后很可能具有其原始值。因此,您最好直接调用Swap(),而不是使用包装器函数。