- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
是否有更好的方法将 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;
}
我正在寻找有关空间或速度或两者的建议...
EDIT: It should be noted that
_marshaller.sendSysex()
cannot throw.
跟进:
我认为值得重述一切,因为评论非常有启发性(除了火焰 war )。 :-P
所问问题的答案...
使用std::copy
大局观:
与其简单地提高代码的原始性能,不如考虑为代码库增加健壮性和生命周期。
我忽略了 RAII - 资源获取即初始化。通过朝另一个方向前进并稍微降低性能,我可以获得很大的弹性 yield (正如@PaulMcKenzie 和@WhozCraig 所指出的)。事实上,我什至可以将我的代码与依赖项的更改隔离开来!
最终解决方案:
在这种情况下,我实际上可以访问(并且能够更改)更大的代码库——通常情况并非如此。我重新评估*我从使用 std::deque
中获得的好处,并将整个底层容器交换为 std::vector
。从而节省容器交换的性能损失,并获得连续数据和 RAII 的好处。
*我选择了 std::deque
,因为在发送之前我总是需要 push_front
两个字节来完成我的字节数组。但是,由于它始终是两个字节,我能够用两个虚拟字节填充 vector 并通过随机访问替换它们 - O(n) 时间。
最佳答案
拥抱 C++ 标准库。假设 _tx
真的是std::deque<uint8_t>
, 一种简单的方法是:
std::vector<uint8_t> msg(_tx.cbegin(), _tx.cend());
_marshaller.sendSysex(firmata::I2C_REQUEST, msg.size(), msg.data());
这会分配适当大小的连续缓冲区,从源迭代器对复制内容,然后调用您的发送操作。 vector 将在作用域退出时自动清理,如果构建它的分配以某种方式失败,则会抛出异常。
标准库提供了大量的方法来处理数据,特别是给定迭代器标记从哪里开始,从哪里停止。不妨利用它来发挥你的优势。此外,让 RAII 像这样处理实体的所有权和清理而不是手动内存管理几乎总是更好的方法,应该受到鼓励。
总而言之,如果您需要连续性(并且从发送调用的外观判断,这正是您这样做的原因),那么从非连续空间复制到连续空间几乎是您唯一的选择,而且占用空间和复制时间。你无能为力避免这种情况。我想看看 std::deque
的实现细节并且可能做一些像堆叠发送调用这样的事情是可能的,但我严重怀疑会有任何返回,唯一的节省可能会在多次发送调用中消失。
最后,还有一个可能值得考虑的选项。看看这一切的来源。是std::deque
真的有必要吗?例如,当然是您在其他地方构建该容器。如果您可以使用 std::vector
高效或接近高效地执行该构建操作,然后整个问题就消失了,因为您可以发送它。
例如,如果您知道(可证明)您的 std::deque
永远不会大于某个尺寸 N
, 你可以预先调整 std::vector
的大小或类似的连续 RAII 保护分配,为 2*N
在大小上,在中间启动前后迭代器对,并通过向后遍历 fore 迭代器来添加数据,或者通过向前遍历 aft 迭代器来添加数据。最后,您的数据将在船首和船尾之间是连续的,剩下的就是发送。不需要拷贝,但仍然需要添加空间。这一切都取决于确定地知道最大消息大小。如果您可以使用它,那么它可能是一个值得分析的想法。
关于c++ - 将 std::deque 内容复制到字节数组的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45260300/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!