我在C++中读过一篇关于"命名循环习语"的文章:http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Loop
这个成语允许我们写这样的东西:
named(outer)
for(int i = 0 ; i < rows ; ++i) {
named(inner)
for(int j = 0 ; j < cols ; ++j) {
if(some_condition)
break(outer); // exit the 'outer' loop
}
}
Run Code Online (Sandbox Code Playgroud)
这样的构造已经作为许多语言的核心特征存在,例如Java.
根据这篇文章,它可以通过定义两个邪恶的宏来用C++实现:
#define named(blockname) goto blockname; \
blockname##_skip: if (0) \
blockname:
#define break(blockname) goto blockname##_skip;
Run Code Online (Sandbox Code Playgroud)
我知道很多人都想放弃使用goto.我个人发现它在极少数情况下很有用,特别是当我想要break一堆嵌套循环时.这个成语在我看来是一个更清洁的解决方案,但是可以在实际代码中使用它吗?
在本文的讨论页面上,可以阅读:
"不要这样做.你最终会陷入地狱"
所以我的问题是:使用命名循环习语有什么缺点?危险吗 ?如果是,为什么?
奖金问题:是否有可能continue同样实施命名?(我认为使用named(...) for(...;...;...) {}语法是不可能的,但谁知道呢?)
编辑:我同意你的意见,重新定义关键字是令人讨厌的.那么使用#define breakLoop()呢?
该文档没有提及任何相关内容(http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-uniq).
此外,它是使用天真的O(n ^ 2)搜索或其他类似哈希映射?在后一种情况下,我应该明白,我的元素必须有一个正确实施hash和eql?时,我想他们unicize?
C++ 11标准说(或者至少是我拥有的版本 - 而不是最终的版本):
没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数.
我理解为什么不能从有状态lambda获取函数指针,因为函数指针本身不能保存任何数据.
但是当捕获的对象只是静态成员/静态变量时,没有这样的限制,因为对捕获的对象的引用可以在函数本身中进行硬连线.
struct A {
static int count = 0;
void foo() {
static int bar = 0;
auto fun = [&]()->void {
count++;
bar++;
};
void(*ptrFun)();
ptrFun = fun; // forbidden by the quoted wording
}
};
Run Code Online (Sandbox Code Playgroud)
一旦前者无状态,为什么不总是可以将lambda转换为函数指针?我错过了什么或者委员会忘记了这一点吗?
这个问题来自于这个问题:命名循环成语:危险吗?.对于那些不想阅读原始问题的人来说,这是关于做这样的事情:
named(label1) for(int i = 0 ; i < 10 ; i++) {
for(int j = 0 ; j < 10 ; j++) {
if(some_condition)
break(label1); // exit outer loop
}
}
Run Code Online (Sandbox Code Playgroud)
这个新问题是关于"命名循环"习语的改进版本.如果你懒得阅读这篇文章,你可以直接转到这篇文章的"例子"部分,清楚地了解我在说什么.
不幸的是,这个问题很快就结束了(后来又被重新开放)因为它更像是一个利弊辩论,而不是一个纯粹的技术问题.它似乎不符合SO Q&A格式.而且,我提出的代码有几个缺陷:
break由宏重新定义它使一些可怕的东西可编译(至少使用MSVC):
int foo() {
named(label1) for(int i = 0 ; i < 10; i++)
{
if(some_condition)
{
break(label1); // here it's ok, the behavior is obvious
}
}
break(label1); // it compiles fine without warning... but the …Run Code Online (Sandbox Code Playgroud)我正在研究一种算法,该算法需要对可能很长的视频(至少 30 分钟)中的视频帧进行非常快速的随机访问。我目前正在使用 OpenCV 的 VideoCapture 来阅读我的视频,但搜索功能要么坏了要么很慢。到目前为止,我发现最好的方法是在 MKV 容器内使用 MJPEG 编解码器,但速度不够快。
我可以选择任何视频格式,甚至可以创建一个新格式。存储空间不是问题(当然在某种程度上)。唯一的要求是在视频中的任何位置获得尽可能快的搜索时间。理想情况下,我希望能够同时访问多个帧,利用我的四核 CPU。
我知道关系数据库非常适合存储大量数据,它们允许同时读取访问,并且在使用索引时速度非常快。
SQLite 是否适合我的特定需求?我计划将每个视频帧压缩为 JPEG 格式,并使用帧编号上的索引来快速访问它们。
编辑:对我来说,一帧只是一个图像,而不是整个视频。一个 3000 万视频 @ 25 fps 包含 30*60*25=45000 帧,我希望能够使用其编号快速获取其中一个。
编辑:对于那些可能感兴趣的人,我最终实现了一个自定义视频容器,将每一帧保存在固定大小的块中(因此,可以直接计算任何帧的位置!)。图像使用 turbojpeg 库压缩,文件访问是多线程的(对 NCQ 友好)。瓶颈不再是 HDD,我终于获得了更好的性能 :)