Google Protocol Buffers RepeatedField无operator[]?Caffe数据写入编译错误
解决Protobuf RepeatedField无法使用operator[]赋值的问题
哈哈,刚接触Protocol Buffer确实容易踩这个小细节坑!你碰到的问题根源在于:google::protobuf::RepeatedField的operator[]是只读访问的,它只能用来读取元素的值,没办法直接通过它赋值修改元素。
为什么你的代码编译失败?
当你尝试datumFloatData->operator[](caffe_ix) = ...或者引用方式datumFloatData_ref[2] = 1.0f时,编译器报错说没有operator[]成员,本质是因为这个运算符返回的是const T&(不可修改的引用),根本不支持赋值操作。Protobuf设计这个运算符就是给只读场景用的——比如你只是想读取某个位置的元素值,那float val = datumFloatData->operator[](caffe_ix);是完全没问题的。
正确的修改方式
要修改RepeatedField中已存在的元素,官方提供的正确方法是调用Mutable(int index)函数,它会返回一个指向对应位置元素的非const指针,你只需要解引用这个指针就能完成赋值。就像你自己找到的修复方案:
*datumFloatData->Mutable(caffe_ix) = (float)(0.5 * (z_pos + 1.0));
这个写法是完全符合Protobuf API规范的,放心用就好。
额外补充
- 如果你是要批量添加新元素,你之前用的
Add()方法是完全正确的,比如:for(int32_t ix{0}; ix < ix_max; ++ ix) { datumFloatData->Add(-1.0f); } - 除了
Mutable(),你也可以用Set(int index, const T& value)方法直接赋值,比如:
这个写法更直观,效果和用datumFloatData->Set(caffe_ix, (float)(0.5 * (z_pos + 1.0)));Mutable()是一样的。
刚开始用Protobuf的时候很容易把它当成STL的vector来用,但它的API设计有自己的考量,记住「只读用operator[]/Get(),修改用Mutable()/Set()」就不会踩这个坑啦!
内容的提问来源于stack exchange,提问作者user2138149




