【发布时间】:2017-12-28 20:12:18
【问题描述】:
有没有更好的方法将std::deque 的内容复制到字节数组中?似乎 STL 中应该有一些东西可以做到这一点。
// Generate byte-array to transmit
uint8_t * i2c_message = new uint8_t[_tx.size()];
if ( !i2c_message ) {
errno = ENOMEM;
::perror("ERROR: FirmataI2c::endTransmission - Failed to allocate memory!");
} else {
size_t i = 0;
// Load byte-array
for ( const auto & data_byte : _tx ) {
i2c_message[i++] = data_byte;
}
// Transmit data
_marshaller.sendSysex(firmata::I2C_REQUEST, _tx.size(), i2c_message);
_stream.flush();
delete[] i2c_message;
}
我正在寻找空间或速度或两者的建议...
编辑:需要注意的是
_marshaller.sendSysex()不能抛出。
跟进:
我认为值得回顾一下所有内容,因为 cmets 非常有启发性(除了火焰战争)。 :-P
问题的答案...
使用std::copy
大局:
与其简单地提高代码的原始性能,不如考虑为代码库增加健壮性和寿命。
我忽略了 RAII - 资源获取就是初始化。通过朝另一个方向前进并稍微降低性能,我可以在弹性方面获得巨大收益(正如@PaulMcKenzie 和@WhozCraig 所指出的)。事实上,我什至可以将我的代码与依赖项的变化隔离开来!
最终解决方案:
在这种情况下,我实际上可以访问(并且能够更改)更大的代码库 - 通常情况并非如此。我重新评估了使用std::deque 所带来的好处,并将整个底层容器换成了std::vector。从而节省容器交换的性能损失,并获得连续数据和 RAII 的好处。
*我选择了std::deque,因为在发送之前我总是需要push_front 两个字节来完成我的字节数组。然而,由于它总是两个字节,我能够用两个虚拟字节填充向量并用随机访问替换它们 - O(n) 时间。
【问题讨论】:
-
std::copy()也许? -
我只见过
std::copy用于从数组复制到容器,而不是相反。 -
首先,我会使用
std::vector<uint8_t>。其次,我会使用迭代器构造函数来构建相同的。这消除了大部分代码,包括给你reliable RAII。向量的data()成员,或第一个元素的地址,将授予您指向您似乎正在寻找的连续数据的指针。 -
假设
std::deque是基于std::vector,你同样可以很好地使用它。 -
@user0042
std::deque没有被标准规定为基于std::vector。这样做毫无意义,因为这两种容器类型在几个任务上的表现非常不同。两者都是随机可访问的容器,但双端队列专门用于快速端(前端或后端)插入和移除,而向量提供保证的连续性;双端队列没有提供的东西,以及为什么 OP 这样做的原因。