没有宏的更快的常量字符串附加

时间:2013-08-08 15:01:10

标签: c++

因此,在组合字符串时,通常会有常量组件,例如:

std::string s;
s += initial_string;
s += "const string";
s += terminating_string;

这只是一个演示,字符串操作可能会更加复杂和深入。因此,在执行const部分时,实现最终“不知道”长度并有效地对其进行strlen()。显然这是一种浪费,因为在编译时已知长度。我已经测试过用这个替换const字符串部分要快得多(无论出于何种原因,在x64中更多):

s.append("const string",12);

实际计算角色是烦人的,耗时且容易出错的,所以这样做会更好一点:

s.append("const string",sizeof("const string")-1);

这仍然有点容易出错(即更改第一部分但忘记更改第二部分)所以宏可以帮助这个:

#define strnsizeof(s) s,sizeof(s)-1
s.append(strnsizeof("const string"));

问题1:任何人都有更好/更清洁的解决方案吗?

我还有一个扩展的字符串类,我使用<<运算符来连接字符串和各种其他对象类型。类似的问题在这里,这很好,干净(对我来说):

s << initial_string << "const string" << terminating_string;

当我有一个运算符用于我自己的对象类型(其长度是一个组件)时,追加操作快速而简单,但当它再次获得const char *时,我的长度均匀虽然它在编译时是不变的。所以我可以通过创建一个小const char *和长度的小结构来加快速度:

s << initial_string
    << MyStr::ConstBuf(strnsizeof("const string"))
    << terminating_string;

男孩变得丑陋。所以我也可以解决这个问题,例如:

#define MyStrConst(s) MyStr::ConstBuf(s,sizeof(s)-1)
s << initial_string
    << MyStrConst("const string")
    << terminating_string;

更好,但不是很好。

问题2:有人比封装常量字符串有更好/更清晰的解决方案吗?

5 个答案:

答案 0 :(得分:3)

对该问题的评论产生了如下模板:

template<size_t SZ> std::string& operator<<( std::string &s, const char(&arr)[SZ] ) {
    s.append( arr, SZ-1 );
    return s;
}

因此,在执行以下操作时,不使用s += "const string"模板:

s << "const string"

此外,我能够更新我的扩展字符串类,以便以下使用模板来获得常量大小:

s << initial_string << "const string" << terminating_string;

编辑:这不能按预期工作:

typedef struct { char buffer[32]; } ST;
ST st = { "1234" };
s << st.buffer;  // results in s with size 31!

这可以通过非const模板解决,例如:

template<size_t SZ> std::string& operator<<( std::string &s, char(&arr)[SZ] ) {
    s.append( arr ); // NOTE not using SZ here so a strlen happens
    return s;
}

现在:

s << st.buffer;  // results in s with size 4

除了:

const ST cst = &st;
s << cst.buffer;  // results in s with size 31 again...

buffer位于class时出现同样的问题,正如您所期望的那样。

答案 1 :(得分:2)

写信给您的编译器制造商,并询问他们为什么不针对这种情况进行优化。然后,希望他们将常量字符串连接添加到优化列表中,每个人的代码都会更快,而无需做任何事情!

这将是我最喜欢的解决方案。

答案 2 :(得分:0)

仅仅是:

const std::string const_string("const string");
std::string s;
s += initial_string;
s += const_string;
s += terminating_string;

答案 3 :(得分:0)

我无法访问MSVC编译器。保留足够大的缓冲区会改善性能吗?

沿着这些方向的东西

#include <iostream>
#include <string>

using namespace std;

string fast_concat(string s, const string& terminating_string) {

  static const string const_string("const string");

  s.reserve(s.size() + const_string.size() + terminating_string.size());

  s.append(const_string);

  s.append(terminating_string);

  return s;
}

int main() {

  cout << fast_concat("initial_string, ", ", terminating string") << endl;

}

(我希望在按值捕获第一个参数时以及在返回结果时进行移动。)

答案 4 :(得分:0)

以下是使用模板

在编译时获取strlen的方法
#include <iostream>
#include <string>

using namespace std;

template <size_t N>
void concat_char_array(string& s, const char (&array)[N]) {

    s.append(array, N-1);
}

string fast_concat(string s, const string& terminating_string) {

  concat_char_array(s, "const string");

  s.append(terminating_string);

  return s;
}

int main() {

  cout << fast_concat("initial string, ", ", terminating string") << endl;

}

它应该和宏一样快。