C 中的字符串串联函数
String concatenation function in C++
我知道+
操作员加入2个std::string
对象。并加入多个字符串的方法。但是我想知道表演。该答案说明了+
操作员与方法(在Python中)相比为何效率低下。在C 标准库中加入多个字符串吗?
操作员超载和方法调用之间没有性能差异 - 取决于调用上下文。在您应该担心的时刻,您是微观优化的。
这是一个抽象的示例,展示了概念。
class MyString
{
public:
// assume this class is implemented
std::string operator+(const std::string &rhs) const
{
return concatenate(rhs);
}
std::string concatenate(const std::string &rhs) const
{
// some implementation
}
};
MyString str1, str2;
// we can use the operator overload
std::string option1 = str1 + str2;
// or we can call a method
std::string option2 = str1.concatenate(str2);
运算符过载(大部分是)避免输入冗长的方法调用,例如后一个示例。它使代码更加干净和简洁。
如果您专门谈论2个以上字符串的性能,这是一种不同的情况。将对象分解为一个方法调用更具性能,因为它避免构建更多的临时对象。如果没有新的数据结构,您将无法做到这一点。
使用上面的类,我们将使用一个表达式中的+
运算符将一堆对象串在一起。
std::string bigConcatenation = str1 + str2 + str1 + str2 + str1;
首先,如果您首先担心性能,您可能不会这样做。也就是说,这是对正在发生的事情的相当不错的近似值(假设编译器没有进行优化)。
std::string bigConcatenation = str1;
bigConcatenation = bigConcatenation + str2;
bigConcatenation = bigConcatenation + str1;
bigConcatenation = bigConcatenation + str2;
bigConcatenation = bigConcatenation + str1;
这不是理想的原因,每个分配都会创建一个临时对象,将它们添加在一起,然后将结果分配回bigConcatenation
。
在不使用任何额外的容器的情况下,根据此答案,执行此操作的最佳方式就是这样(提示:在此过程中没有创建临时性)。
std::string bigConcatenation = str1;
bigConcatenation += str2;
bigConcatenation += str1;
bigConcatenation += str2;
bigConcatenation += str1;
串联字符串很少在C 中的瓶颈足够多,几乎没有人尝试优化它。
如果您遇到了这样一个重要的情况,那么这样做很重要,但是避免问题相当轻松,更改很小,因此a = b + c + d + e;
保持 a = b + c + d + e;
而不是诸如a.concat(b, c, d, e);
之类的东西(我会补充的是,实际上是使工作良好的非常不乏味)。根据所涉及的类型,您可能需要添加代码以将列表中的第一个项目转换为正确的类型。对于显而易见的示例,我们不能超载operator+
在字符串文字上工作,因此,如果您想将串联字符串文字合并在一起,则必须明确将第一个转换为其他类型。
"技巧"在称为表达模板的东西中(在这种情况下,它甚至不需要是模板)。您要做的是创建一个字符串构建器对象,该对象将其operator+
超载以存储指针/引用到源字符串。反过来,这将转换为std::string
,从而将所有源字符串的长度加在一起,将它们串联到std::string
中,最后返回整个字符串。例如,代码看起来像这样:
#include <string>
#include <iostream>
#include <vector>
#include <numeric>
#include <cstring>
namespace string {
class ref;
class builder {
std::vector<ref const *> strings;
public:
builder(ref const &s) { strings.push_back(&s); }
builder & operator+(ref const &s) {
strings.push_back(&s);
return *this;
}
operator std::string() const;
};
class ref {
char const *data;
size_t N;
public:
ref(char const *s) : data(s), N(std::strlen(s)) {}
ref(char const *s, size_t N) : data(s), N(N-1) {}
size_t length() const { return N; }
operator char const *() const { return data; }
builder operator+(ref const &other) {
return builder(*this) + other;
}
};
builder::operator std::string() const {
size_t length = std::accumulate(strings.begin(), strings.end(),
size_t(),
[](size_t a, auto s) { return a + s->length(); });
std::string ret;
ret.reserve(length);
for (auto s : strings)
ret.append(*s);
return ret;
}
}
string::ref operator "" _s(char const *s, unsigned long N) { return string::ref(s, N); }
int main() {
std::string a = "b"_s + "c" + "d" + "e";
std::cout << a << "n";
}
请注意,当您上面编写代码时,如果您将所有文字转换为 string_ref
s,则您(至少在理论上)获得了一些运行时效率:
std::string a = "b"_s + "c"_s + "d"_s + "e"_s;
以这种方式,编译器在编译时测量每个文字的长度,并将长度直接传递给用户定义的文字操作员。如果您直接传递字符串文字,则该代码使用std::strlen
在运行时测量长度。
您可以使用弦流记住添加指令#include
进入类的标题文件或类的源文件。无论哪个具有您的方法定义。
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何从void函数输出字符串
- 使用用户定义函数的字符串反转
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- 在c++构造函数中使用随机字符串生成器
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- C++:如何使函数只返回作为列表一部分的字符串
- 如何在C++中的同一函数中使用字符串和双精度
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- 一个函数,用于查找字符串1包含字符串2 c++的次数
- 对函数 PlaySound 使用字符串变量
- 具有多个模板的模板函数,用于特定数据类型(如字符串)?
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- Visual c ++,使用字符串引用/指针调用 dll 函数
- 构造函数字符串参数未设置窗口标题
- C++默认构造函数:字符串参数与字符串参数()
- 使用函数C++字符串输入
- c++模板函数字符串类型不匹配