无需宏即可更快地追加常量字符串
Faster constant string appending without macro
所以在组合字符串时,通常有常量组件,例如:
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:有人有比封装常量字符串更好/更干净的解决方案吗?
对问题的评论产生了如下所示的模板:
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
处于class
中时,同样的问题。
写信给你的编译器制造商,问他们为什么不针对这种情况进行优化。然后,希望他们将常量字符串串联添加到优化列表中,并且每个人的代码都会更快,而无需执行任何操作!
这将是我最喜欢的解决方案。
那只是:
const std::string const_string("const string");
std::string s;
s += initial_string;
s += const_string;
s += terminating_string;
我无法访问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;
}
(我希望在按值捕获第一个参数以及返回结果时移动。
以下是使用模板在编译时获得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;
}
它应该和宏一样快。
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 什么时候在C++中返回常量引用是个好主意
- 代理对象的常量正确性
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 通过多个头文件使用常量变量
- 在cuda线程之间共享大量常量数据
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 是默认情况下分配给char数组常量的值
- 私有类型的静态常量成员
- 类似枚举的计算常量
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 为什么我可以通过引用修改常量返回
- 如何创建长度由常量参数指定的数组
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 隐式常量/非常量运算符布尔
- 无需宏即可更快地追加常量字符串
- C++常量数组追加