2010-03-02 150 views
3

我正在开发一个GUI框架,我希望所有的元素都可以通过最多8个字符的ASCII字符串来标识(否则7就可以)。快速64位比较

每当一个事件被触发(有些只是点击,但有些是连续的),该框架将回调到编号,并将其值的客户端代码。我可以使用实际的字符串和strcmp(),但我想这是非常快的(对于移动设备),所以我想用char常量(例如int id ='BTN1';),所以你会做一个int比较来测试id。但是,4个字符不够可读。

我尝试了一个实验,一些喜欢 - 长整型ID = L'ABCDEFG“;

...但它看起来好像烧焦常量只能容纳4个字符,而唯一让long int类型的字符常量给你是你4个字符的两倍宽的能力,不具备两倍的字符。我在这里错过了什么吗?

我想很容易让编写客户端代码的人。 gui存储在xml中,所以id从字符串中加载,但是会在客户端代码中写入常量来比较这些常量。

因此,长期和短期的是,我正在寻找一个跨平台的方式来做到快速7-8字符比较,任何想法?

+2

多少万每秒你做比较?不要为它出汗,它的速度足够快。 – 2010-03-02 15:45:30

+0

如果你的目标是给你的组件一个命名方案,不要使用long-char对ascii的支持。 – 2010-03-02 15:47:50

+0

这可能不便携。根据C++标准,多字符文字(多个字符之间的字符)的值是实现定义的。检查你的实现的文档,看看它是否在做你想做的事情,并检查所有可用于实现的实现,看看它们是否都做同样的事情。 – 2010-03-02 16:38:14

回答

4

您确定这不是过早优化吗?你有没有分析另一个纯粹来自字符串比较的缓慢的GUI框架?为什么你确定字符串比较太慢?当然你不是在做多串比较。此外,考虑strcmp应该有一个接近最佳的实现,可能会写在为您正在编译的CPU量身定制的汇编中。

反正其他框架只是使用命名整数,例如:

static const int MY_BUTTON_ID = 1; 

你可以考虑代替,避免了串问题完全。或者,您可以简单地编写一个帮助函数将const char [9]转换为64位整数。这应该接受一个以空字符结尾的字符串“像这样”,最多8个字符(假设你打算抛弃空字符)。然后你的程序传递64位整数,但程序员正在处理字符串。

编辑:这里有一个快速的函数,把一个字符串中的数字:

__int64 makeid(const char* str) 
{ 
    __int64 ret = 0; 
    strncpy((char*)&ret, str, sizeof(__int64)); 
    return ret; 
} 
+0

我见过很多gui框架使用int ids,但由于我的框架是基于界面构建器的,编码器必须将数字复制到他们的代码中(不雅),或者界面构建器必须生成一个头文件为每个元素定义,这将不适用于框架的一些应用 我认为你是完全正确的,我没有做很多比较,所以我会坚持使用字符串。我敢肯定在我的代码中会有更大的瓶颈!谢谢! – mazbox 2010-03-02 16:53:14

+0

为什么选择这个答案如果你要坚持使用字符串,还有其他人花时间回答你的具体问题? ? – 2010-03-02 16:55:23

+0

也许你没有得到我答案的最后部分,所以我编辑了一个函数来显示。如果你调用makeid(“我的id”),你会得到一个__int64,并将字符串复制到它。这使您可以使用程序员输入字符串的便利性进行整数比较。注意它忽略了8号以后的任何字符。 – AshleysBrain 2010-03-02 22:42:45

1

轻松搞定预轧组件

binary search tree为赢 - 你从集和地图的最STL实现获得red-black树,所以你可能要考虑这一点。

Intrusive versions当您将容器节点移动很多时(通常情况下),STL容器执行的效果会更好 - 但是它们有相当多的注意事项。

具体意见 - 第一替代

如果我是你,我会坚持到64位整数类型,并在介入式容器将其捆绑,并使用升压提供的库。然而,如果你对这类事情还不熟悉,那么使用stl :: map它在概念上更容易掌握,并且泄漏资源的可能性较小,因为这里有更多关于这些类型的容器和最佳实践的文献和指南。

替代2

你正在试图解决我相信这个问题:是有它映射到手柄一个全球性的命名方案。您可以创建名称映射到手柄,让您可以使用的名称检索句柄:

// WidgetHandle is a polymorphic base class (i.e., it has a virtual method), 
// and foo::Luv implement WidgetHandle's interface (public inheritance) 
foo::WidgetHandle * LuvComponent = 
      Factory.CreateComponent<foo::Luv>("meLuvYouLongTime"); 
.... 

.... // in different function 
foo::WidgetHandle * LuvComponent = 
      Factory.RetrieveComponent<foo::Luv>("meLuvYouLongTime"); 

方案2是IPC一个常见的成语,你在一个过程中创建一个IPC型说的管道,你可以请求内核以名称检索管道的另一端。

+0

感谢您的回答。我想我一直在寻找最少的LOC版本,对于程序员来说最简单的方法就是尽可能快地尝试。我已经对它的组件检索部分进行了排序,它只是确定事件来自哪个组件。 – mazbox 2010-03-04 11:44:15

1

string interning概念可以针对此问题是有用的,转动串比较入指针进行比较。

+0

我喜欢只比较指针的想法,但我试图得到一个解决方案,对于编码者的角度来看也是最优的(也许我不能拥有两全其美),例如(id = SOME_MACRO('myButton')){ doSomethingWith(value); (id == SOME_MACRO('mySlider')){ doSomethingElse(value); } } 在这样的代码中,文字'myButton'和'mySlider'的代码很少,程序员编写的代码更少。 也许我可以把SOME_MACRO()变成一个哈希函数... – mazbox 2010-03-02 15:57:44

4

一种可能性是定义你的ID作为一个64位整数的工会和8个字符的字符串:

union ID { 
    Int64 id;  // Assuming Int64 is an appropriate typedef somewhere 
    char name[8]; 
}; 

现在你可以做这样的事情:

ID id; 
strncpy(id.name, "Button1", 8); 
if (anotherId.id == id.id) ... 
+0

聪明...(15个字符) – 2010-03-04 12:01:49

+0

我在过去做过同样的事情,它运行良好。 – 2015-04-03 18:44:40

0

我见区分代码中易于阅读的标识符和传递的表示。

您可以使用枚举类型(或常量的大头文件)来表示标识符吗?那么枚举类型的名称就可以像你期望的那样长和有意义,并且仍然适合于(我猜测)几个字节。

0

在C++ 0x中,你就可以使用user-defined string literals,所以你可以添加喜欢7chars..id"7chars.."id东西:

template <char...> constexpr unsigned long long operator ""id(); 
constexpr unsigned long long operator ""id(const char *, size_t); 

虽然我不知道你可以使用constexpr的第二个。