一、repeated的定义以及使用
protobuf中repeated是一种用来表示一个字段可以被重复多次的数据类型,它类似于C++中的vector和Java中的List,可以用来存储一组值。
syntax = "proto3"; message Person { string name = 1; int32 age = 2; repeated string address = 3; }
在上述代码中,我们定义了一个Person消息对象,其中address是一个repeated类型的属性,表示可以有多个地址。
使用repeated的好处在于它可以在一个字段中存储多个数据,这样可以减少定义属性的个数,提高数据的可效率性。
二、repeated的序列化和反序列化
序列化和反序列化是protobuf最重要的功能之一,可以将消息对象转化为二进制格式,便于网络传输和存储。repeated的序列化和反序列化操作与标量类型基本相同,可以借助protobuf库中的函数实现。
例如,我们需要对上述定义的Person消息对象进行序列化和反序列化操作,可以参考下面的代码:
#include #include #include "person.pb.h" //protobuf生成的头文件 using namespace std; int main() { //创建一个Person对象,并设置属性值 tutorial::Person person; person.set_name("张三"); person.set_age(20); person.add_address("北京市"); person.add_address("上海市"); //将Person对象序列化为二进制数据 string buffer; person.SerializeToString(&buffer); //将二进制数据反序列化为Person对象 tutorial::Person newPerson; newPerson.ParseFromString(buffer); //输出newPerson对象的属性值 cout << "姓名:" << newPerson.name() << endl; cout << "年龄:" << newPerson.age() << endl; cout << "地址:"; for (int i = 0; i < newPerson.address_size(); i++) { cout << newPerson.address(i) << " "; } cout << endl; return 0; }
可以看到,在上述代码中,我们首先创建了一个Person对象,并设置了属性值,然后通过SerializeToString函数将其序列化为二进制数据。反序列化时,则需要先创建一个空的Person对象,通过ParseFromString函数将二进制数据反序列化为新的对象。
三、repeated的默认值
repeated字段的默认值是一个空列表,该列表包含0个元素。当我们需要添加元素时,可以通过调用add_XXX函数向列表中添加元素。
下面是一个示例代码:
syntax = "proto3"; message Person { string name = 1; int32 age = 2; repeated string address = 3 [default = "北京市"]; }
在上述代码中,我们通过在address字段后加上default选项,指定了address字段的默认值为“北京市”。这意味着,在创建Person消息对象时,如果没有为address属性赋值,那么该属性会默认为“北京市”。当然,我们也可以在创建对象后,通过调用add_address函数向address列表中添加元素。
四、repeated字段的遍历
遍历repeated字段的方式与遍历C++中的vector类似,可以使用for循环来迭代列表中的每一个元素。下面是一个示例代码:
#include #include "person.pb.h" using namespace std; int main() { //创建一个Person对象,并向address字段中添加三个元素 tutorial::Person person; person.add_address("北京市"); person.add_address("上海市"); person.add_address("广州市"); //遍历address字段,并输出每一个元素的值 for (int i = 0; i < person.address_size(); i++) { cout << person.address(i) << endl; } return 0; }
五、repeated字段和map的比较
在进行开发时,我们有时需要在消息对象中存储一些键值对数据,这时可以考虑使用map数据类型。与repeated不同,map类型可以直接通过键值访问元素,而无需使用循环遍历。下面是一个示例代码:
syntax = "proto3"; message Person { string name = 1; int32 age = 2; map address = 3; }
在上述代码中,我们使用了map类型来存储地址信息。代码中的map使用了string类型作为键和值的类型。对于map类型的序列化和反序列化操作,与repeated的操作类似,都可以借助protobuf库中提供的函数实现。
但是需要注意的是,由于map类型是一种关联式数据结构,其底层实现依赖于红黑树等算法,因此其性能相对于repeated略低。所以,在实际开发中,我们需要根据具体的需求选择合适的数据类型。
原创文章,作者:MTALN,如若转载,请注明出处:https://www.506064.com/n/331638.html