7

所以在组合字符串的时候,往往会有常量的组成部分,例如:

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

这只是一个演示,字符串操作可能更加复杂和深入。因此,在执行 const 部分时,实现最终“不知道”长度并有效地strlen()对其进行了 a 。显然这是一种浪费,因为长度在编译时是已知的。我已经测试过用它替换 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 *因此,我可以通过创建一个采用 a和 length的小结构来加快速度:

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:有没有比封装常量字符串更好/更清洁的解决方案?

4

5 回答 5

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!

这可以通过非常量模板来解决,例如:

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在 a 中时出现同样的问题。class

于 2013-08-08T16:15:05.640 回答
2

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

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

于 2013-08-08T15:19:07.783 回答
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;

}

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

于 2013-08-08T16:07:43.107 回答
0

只是:

const std::string const_string("const string");
std::string s;
s += initial_string;
s += const_string;
s += terminating_string;
于 2013-08-08T15:22:09.683 回答
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;

}

它应该和使用宏一样快。

于 2013-08-08T16:22:22.037 回答