C++学习笔记-StringView

std::string_view是C++17引入的一个轻量级、不可变的字符串视图类,提供了一种高效的方式来查看字符串数据,而不需要拷贝字符串数据。它可以显著减少不必要的内存分配,提高程序性能。

内存分配问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <string>
#include <string_view>

static uint32_t s_AllocCount = 0;

/* 重载new操作符来跟踪内存分配,仅用于演示 */
void* operator new(size_t size)
{
    s_AllocCount++;
    std::cout << "Allocation: " << size << " bytes" << std::endl;
    return malloc(size);
}

void Print(const std::string& str)
{
    std::cout << "String: " << str << std::endl;
}

void Print(std::string_view str)
{
    std::cout << "StringView: " << str << std::endl;
}

void MemoryAllocationDemo()
{
    std::cout << "=== Memory Allocation Demo ===" << std::endl;
    
    s_AllocCount = 0;
    std::cout << "Initial allocation count: " << s_AllocCount << std::endl;
    
    /* 一般情况下3次内存分配 */
    std::cout << "\n1. Traditional string operations:" << std::endl;
    std::string helloWorld = "Hello World!"; // 创建string时会进行一次内存分配
    std::string hello = helloWorld.substr(0, 5);
    std::string world = helloWorld.substr(6, 5);
    
    std::cout << "After string operations, allocation count: " << s_AllocCount << std::endl;
    Print(hello);
    Print(world);
    
    /* 使用string_view只需要1次内存分配 */
    s_AllocCount = 0;
    std::cout << "\n2. Using string_view (with string source):" << std::endl;
    std::string helloWorld2 = "Hello World!";
    std::string_view hello2(helloWorld2.c_str(), 5);
    std::string_view world2(helloWorld2.c_str() + 6, 5);
    
    std::cout << "After string_view operations, allocation count: " << s_AllocCount << std::endl;
    Print(hello2);
    Print(world2);
    
    /* 完全不进行内存分配 */
    s_AllocCount = 0;
    std::cout << "\n3. Using string_view (with C-string source):" << std::endl;
    const char* helloWorld3 = "Hello World!";
    std::string_view hello3(helloWorld3, 5);
    std::string_view world3(helloWorld3 + 6, 5);
    
    std::cout << "After string_view operations, allocation count: " << s_AllocCount << std::endl;
    Print(hello3);
    Print(world3);
    
    /*
    总结
    1. std::string_view 是 C++17 中引入的一个轻量级、不可变的字符串视图类型,它提供了一种高效的方式来查看字符串数据,而不需要拷贝字符串数据。这样可以显著减少不必要的内存分配和拷贝操作,从而提高程序性能。
    */
}

int main()
{
    MemoryAllocationDemo();
    return 0;
}

基本用法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <iostream>
#include <string>
#include <string_view>

void BasicStringViewUsage()
{
    std::cout << "=== Basic StringView Usage ===" << std::endl;
    
    // 从C字符串创建
    std::string_view sv1 = "Hello World";
    std::cout << "From C-string: " << sv1 << std::endl;
    
    // 从std::string创建
    std::string str = "Hello C++";
    std::string_view sv2 = str;
    std::cout << "From std::string: " << sv2 << std::endl;
    
    // 从部分字符串创建
    std::string_view sv3(str.data() + 6, 3); // "C++"
    std::cout << "Substring: " << sv3 << std::endl;
    
    // 使用构造函数
    const char* cstr = "Programming";
    std::string_view sv4(cstr, 7); // "Program"
    std::cout << "Partial C-string: " << sv4 << std::endl;
    
    // 基本属性
    std::cout << "\nBasic properties:" << std::endl;
    std::cout << "Length: " << sv1.length() << std::endl;
    std::cout << "Size: " << sv1.size() << std::endl;
    std::cout << "Empty: " << sv1.empty() << std::endl;
    std::cout << "Data pointer: " << (void*)sv1.data() << std::endl;
    
    // 访问字符
    std::cout << "\nCharacter access:" << std::endl;
    std::cout << "First char: " << sv1.front() << std::endl;
    std::cout << "Last char: " << sv1.back() << std::endl;
    std::cout << "Char at index 6: " << sv1[6] << std::endl;
    std::cout << "Char at index 6 (at): " << sv1.at(6) << std::endl;
}

void StringViewOperations()
{
    std::cout << "\n=== StringView Operations ===" << std::endl;
    
    std::string_view sv = "Hello, World! Programming is fun.";
    std::cout << "Original: " << sv << std::endl;
    
    // substr操作
    auto sub1 = sv.substr(0, 5);  // "Hello"
    auto sub2 = sv.substr(7, 5);  // "World"
    auto sub3 = sv.substr(15);    // "Programming is fun."
    
    std::cout << "substr(0, 5): " << sub1 << std::endl;
    std::cout << "substr(7, 5): " << sub2 << std::endl;
    std::cout << "substr(15): " << sub3 << std::endl;
    
    // remove_prefix和remove_suffix
    std::string_view sv_copy = sv;
    sv_copy.remove_prefix(7);  // 移除前7个字符
    std::cout << "After remove_prefix(7): " << sv_copy << std::endl;
    
    sv_copy.remove_suffix(13); // 移除后13个字符
    std::cout << "After remove_suffix(13): " << sv_copy << std::endl;
    
    // 查找操作
    std::cout << "\nFind operations:" << std::endl;
    auto pos1 = sv.find("World");
    auto pos2 = sv.find("Programming");
    auto pos3 = sv.find("xyz");
    
    std::cout << "find('World'): " << (pos1 != std::string_view::npos ? std::to_string(pos1) : "not found") << std::endl;
    std::cout << "find('Programming'): " << (pos2 != std::string_view::npos ? std::to_string(pos2) : "not found") << std::endl;
    std::cout << "find('xyz'): " << (pos3 != std::string_view::npos ? std::to_string(pos3) : "not found") << std::endl;
    
    // 比较操作
    std::cout << "\nComparison operations:" << std::endl;
    std::string_view sv1 = "apple";
    std::string_view sv2 = "banana";
    std::string_view sv3 = "apple";
    
    std::cout << "apple == apple: " << (sv1 == sv3) << std::endl;
    std::cout << "apple == banana: " << (sv1 == sv2) << std::endl;
    std::cout << "apple < banana: " << (sv1 < sv2) << std::endl;
    std::cout << "apple.compare(banana): " << sv1.compare(sv2) << std::endl;
}

int main()
{
    BasicStringViewUsage();
    StringViewOperations();
    return 0;
}

函数参数优化

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <string>
#include <string_view>
#include <vector>

// 传统的字符串参数函数
void processString_old(const std::string& str)
{
    std::cout << "Processing (old): " << str << std::endl;
}

// 使用string_view的优化版本
void processString_new(std::string_view str)
{
    std::cout << "Processing (new): " << str << std::endl;
}

// 字符串分析函数
class StringAnalyzer
{
public:
    static size_t countWords(std::string_view text)
    {
        if (text.empty()) return 0;
        
        size_t count = 0;
        bool inWord = false;
        
        for (char c : text)
        {
            if (std::isspace(c))
            {
                inWord = false;
            }
            else if (!inWord)
            {
                inWord = true;
                count++;
            }
        }
        
        return count;
    }
    
    static bool startsWith(std::string_view text, std::string_view prefix)
    {
        return text.size() >= prefix.size() && 
               text.substr(0, prefix.size()) == prefix;
    }
    
    static bool endsWith(std::string_view text, std::string_view suffix)
    {
        return text.size() >= suffix.size() && 
               text.substr(text.size() - suffix.size()) == suffix;
    }
    
    static std::vector<std::string_view> split(std::string_view text, char delimiter)
    {
        std::vector<std::string_view> result;
        size_t start = 0;
        
        for (size_t i = 0; i <= text.size(); ++i)
        {
            if (i == text.size() || text[i] == delimiter)
            {
                if (i > start)
                {
                    result.push_back(text.substr(start, i - start));
                }
                start = i + 1;
            }
        }
        
        return result;
    }
    
    static std::string_view trim(std::string_view text)
    {
        // 移除前导空白
        size_t start = 0;
        while (start < text.size() && std::isspace(text[start]))
        {
            start++;
        }
        
        // 移除尾随空白
        size_t end = text.size();
        while (end > start && std::isspace(text[end - 1]))
        {
            end--;
        }
        
        return text.substr(start, end - start);
    }
};

void FunctionParameterDemo()
{
    std::cout << "=== Function Parameter Demo ===" << std::endl;
    
    // 测试不同类型的字符串输入
    std::string stdString = "Hello from std::string";
    const char* cString = "Hello from C-string";
    std::string_view stringView = "Hello from string_view";
    
    std::cout << "Using old function (const std::string&):" << std::endl;
    processString_old(stdString);
    processString_old(cString);     // 会创建临时string对象
    // processString_old(stringView); // 编译错误,需要转换
    
    std::cout << "\nUsing new function (string_view):" << std::endl;
    processString_new(stdString);
    processString_new(cString);
    processString_new(stringView);
    processString_new("Hello from literal"); // 直接使用字符串字面量
    
    // 字符串分析示例
    std::cout << "\n=== String Analysis Demo ===" << std::endl;
    
    std::string text = "  Hello, World! This is a test.  ";
    std::cout << "Original text: '" << text << "'" << std::endl;
    
    // 单词计数
    std::cout << "Word count: " << StringAnalyzer::countWords(text) << std::endl;
    
    // 前缀和后缀检查
    std::cout << "Starts with '  Hello': " << StringAnalyzer::startsWith(text, "  Hello") << std::endl;
    std::cout << "Ends with 'test.  ': " << StringAnalyzer::endsWith(text, "test.  ") << std::endl;
    
    // 修剪空白
    auto trimmed = StringAnalyzer::trim(text);
    std::cout << "Trimmed: '" << trimmed << "'" << std::endl;
    
    // 分割字符串
    std::string csv = "apple,banana,cherry,date";
    auto parts = StringAnalyzer::split(csv, ',');
    std::cout << "Split '" << csv << "' by comma:" << std::endl;
    for (size_t i = 0; i < parts.size(); ++i)
    {
        std::cout << "  [" << i << "]: '" << parts[i] << "'" << std::endl;
    }
    
    // 嵌套分析
    std::string multiline = "Line 1: Hello World\nLine 2: Programming\nLine 3: C++ is great";
    auto lines = StringAnalyzer::split(multiline, '\n');
    std::cout << "\nAnalyzing multiline text:" << std::endl;
    for (size_t i = 0; i < lines.size(); ++i)
    {
        auto line = StringAnalyzer::trim(lines[i]);
        std::cout << "Line " << (i + 1) << ": '" << line << "' (" 
                  << StringAnalyzer::countWords(line) << " words)" << std::endl;
    }
}

int main()
{
    FunctionParameterDemo();
    return 0;
}

注意事项和陷阱

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <string>
#include <string_view>
#include <vector>

void DanglingPointerDemo()
{
    std::cout << "=== Dangling Pointer Demo ===" << std::endl;
    
    std::string_view sv;
    
    // 危险:悬空指针
    {
        std::string temp = "Temporary string";
        sv = temp; // sv现在指向temp的数据
        std::cout << "Inside scope: " << sv << std::endl;
    } // temp被销毁,sv现在指向无效内存
    
    // 这里访问sv是未定义行为!
    // std::cout << "Outside scope: " << sv << std::endl; // 危险!
    
    std::cout << "Temporary string went out of scope - sv is now dangling!" << std::endl;
}

std::string_view createStringView_bad()
{
    std::string local = "Local string";
    return local; // 危险:返回指向局部变量的string_view
}

std::string_view createStringView_good()
{
    static const char* global = "Global string";
    return global; // 安全:指向全局数据
}

void LifetimeIssuesDemo()
{
    std::cout << "\n=== Lifetime Issues Demo ===" << std::endl;
    
    // 错误的用法
    std::cout << "Bad usage:" << std::endl;
    auto bad_sv = createStringView_bad();
    // std::cout << bad_sv << std::endl; // 未定义行为
    std::cout << "Returned string_view from function with local string (dangerous!)" << std::endl;
    
    // 正确的用法
    std::cout << "\nGood usage:" << std::endl;
    auto good_sv = createStringView_good();
    std::cout << good_sv << std::endl; // 安全
    
    // 临时对象问题
    std::cout << "\nTemporary object issues:" << std::endl;
    
    // 危险:临时string对象
    std::string_view sv1 = std::string("Temporary") + " string"; // 临时对象立即销毁
    // std::cout << sv1 << std::endl; // 未定义行为
    std::cout << "Created string_view from temporary string (dangerous!)" << std::endl;
    
    // 安全:字符串字面量
    std::string_view sv2 = "String literal"; // 字符串字面量有静态存储期
    std::cout << "From string literal: " << sv2 << std::endl; // 安全
    
    // 安全:持久的string对象
    std::string persistent = "Persistent string";
    std::string_view sv3 = persistent; // 只要persistent存在就安全
    std::cout << "From persistent string: " << sv3 << std::endl;
}

void ModificationIssuesDemo()
{
    std::cout << "\n=== Modification Issues Demo ===" << std::endl;
    
    // string_view是只读的
    std::string_view sv = "Hello World";
    
    // 这些操作都是不可能的(编译错误):
    // sv[0] = 'h';           // 错误:不能修改
    // sv.push_back('!');     // 错误:没有这个方法
    // sv += " more text";    // 错误:没有+=操作符
    
    std::cout << "string_view is read-only: " << sv << std::endl;
    
    // 如果需要修改,必须转换为string
    std::string modifiable(sv);
    modifiable[0] = 'h';
    modifiable += " - modified";
    std::cout << "After conversion to string and modification: " << modifiable << std::endl;
    
    // 原始string_view不受影响
    std::cout << "Original string_view unchanged: " << sv << std::endl;
}

void SubstringIssuesDemo()
{
    std::cout << "\n=== Substring Issues Demo ===" << std::endl;
    
    std::string original = "Hello, World!";
    std::string_view sv = original;
    
    // 创建子字符串视图
    auto hello = sv.substr(0, 5);
    auto world = sv.substr(7, 5);
    
    std::cout << "Original: " << original << std::endl;
    std::cout << "Hello: " << hello << std::endl;
    std::cout << "World: " << world << std::endl;
    
    // 修改原始字符串
    original[7] = 'w'; // 'W' -> 'w'
    
    std::cout << "\nAfter modifying original string:" << std::endl;
    std::cout << "Original: " << original << std::endl;
    std::cout << "Hello: " << hello << std::endl; // 不受影响
    std::cout << "World: " << world << std::endl; // 受到影响!
    
    std::cout << "Note: string_view reflects changes in the underlying data!" << std::endl;
}

void BestPracticesDemo()
{
    std::cout << "\n=== Best Practices Demo ===" << std::endl;
    
    std::cout << "Best practices for string_view:" << std::endl;
    std::cout << "1. Use for function parameters to accept any string type" << std::endl;
    std::cout << "2. Don't store string_view as class members (lifetime issues)" << std::endl;
    std::cout << "3. Don't return string_view from functions (unless pointing to static data)" << std::endl;
    std::cout << "4. Be careful with temporary string objects" << std::endl;
    std::cout << "5. Remember that string_view is read-only" << std::endl;
    std::cout << "6. Use string_view for parsing and analysis, not for storage" << std::endl;
    
    // 好的用法示例
    auto processText = [](std::string_view text) {
        std::cout << "Processing: " << text << " (length: " << text.length() << ")" << std::endl;
    };
    
    std::string str = "Example string";
    const char* cstr = "C-style string";
    
    processText(str);
    processText(cstr);
    processText("String literal");
    processText(std::string_view(str.data() + 8, 6)); // "string"
}

int main()
{
    DanglingPointerDemo();
    LifetimeIssuesDemo();
    ModificationIssuesDemo();
    SubstringIssuesDemo();
    BestPracticesDemo();
    
    return 0;
}

性能比较和实际应用

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
#include <chrono>
#include <algorithm>

// 性能测试
class PerformanceTest
{
public:
    static void stringParameterTest()
    {
        std::cout << "=== String Parameter Performance Test ===" << std::endl;
        
        const int iterations = 100000;
        std::vector<std::string> testStrings;
        
        // 准备测试数据
        for (int i = 0; i < 1000; ++i)
        {
            testStrings.push_back("Test string number " + std::to_string(i));
        }
        
        // 测试const std::string&参数
        auto start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < iterations; ++i)
        {
            processWithString(testStrings[i % testStrings.size()]);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto stringTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        
        // 测试string_view参数
        start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < iterations; ++i)
        {
            processWithStringView(testStrings[i % testStrings.size()]);
        }
        end = std::chrono::high_resolution_clock::now();
        auto stringViewTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        
        std::cout << "const std::string& parameter: " << stringTime.count() << " microseconds" << std::endl;
        std::cout << "string_view parameter: " << stringViewTime.count() << " microseconds" << std::endl;
        std::cout << "Speedup: " << (double)stringTime.count() / stringViewTime.count() << "x" << std::endl;
    }
    
    static void substringTest()
    {
        std::cout << "\n=== Substring Performance Test ===" << std::endl;
        
        const int iterations = 100000;
        std::string largeString(1000, 'x');
        largeString += "target substring here";
        largeString += std::string(1000, 'y');
        
        // 测试string::substr
        auto start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < iterations; ++i)
        {
            volatile auto sub = largeString.substr(1000, 22);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto stringSubstrTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        
        // 测试string_view::substr
        std::string_view sv = largeString;
        start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < iterations; ++i)
        {
            volatile auto sub = sv.substr(1000, 22);
        }
        end = std::chrono::high_resolution_clock::now();
        auto stringViewSubstrTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        
        std::cout << "string::substr: " << stringSubstrTime.count() << " microseconds" << std::endl;
        std::cout << "string_view::substr: " << stringViewSubstrTime.count() << " microseconds" << std::endl;
        std::cout << "Speedup: " << (double)stringSubstrTime.count() / stringViewSubstrTime.count() << "x" << std::endl;
    }

private:
    static void processWithString(const std::string& str)
    {
        volatile size_t len = str.length();
    }
    
    static void processWithStringView(std::string_view str)
    {
        volatile size_t len = str.length();
    }
};

// 实际应用:日志解析器
class LogParser
{
public:
    struct LogEntry
    {
        std::string_view timestamp;
        std::string_view level;
        std::string_view message;
    };
    
    static LogEntry parseLine(std::string_view line)
    {
        LogEntry entry;
        
        // 查找第一个空格(时间戳结束)
        auto firstSpace = line.find(' ');
        if (firstSpace != std::string_view::npos)
        {
            entry.timestamp = line.substr(0, firstSpace);
            line.remove_prefix(firstSpace + 1);
            
            // 查找第二个空格(级别结束)
            auto secondSpace = line.find(' ');
            if (secondSpace != std::string_view::npos)
            {
                entry.level = line.substr(0, secondSpace);
                entry.message = line.substr(secondSpace + 1);
            }
        }
        
        return entry;
    }
    
    static std::vector<LogEntry> parseLog(std::string_view logContent)
    {
        std::vector<LogEntry> entries;
        
        size_t start = 0;
        while (start < logContent.size())
        {
            auto end = logContent.find('\n', start);
            if (end == std::string_view::npos)
            {
                end = logContent.size();
            }
            
            auto line = logContent.substr(start, end - start);
            if (!line.empty())
            {
                entries.push_back(parseLine(line));
            }
            
            start = end + 1;
        }
        
        return entries;
    }
};

// 实际应用:CSV解析器
class CSVParser
{
public:
    static std::vector<std::vector<std::string_view>> parseCSV(std::string_view csvContent)
    {
        std::vector<std::vector<std::string_view>> rows;
        
        size_t lineStart = 0;
        while (lineStart < csvContent.size())
        {
            auto lineEnd = csvContent.find('\n', lineStart);
            if (lineEnd == std::string_view::npos)
            {
                lineEnd = csvContent.size();
            }
            
            auto line = csvContent.substr(lineStart, lineEnd - lineStart);
            if (!line.empty())
            {
                rows.push_back(parseCSVLine(line));
            }
            
            lineStart = lineEnd + 1;
        }
        
        return rows;
    }

private:
    static std::vector<std::string_view> parseCSVLine(std::string_view line)
    {
        std::vector<std::string_view> fields;
        
        size_t start = 0;
        while (start < line.size())
        {
            auto end = line.find(',', start);
            if (end == std::string_view::npos)
            {
                end = line.size();
            }
            
            auto field = line.substr(start, end - start);
            
            // 简单的引号处理
            if (!field.empty() && field.front() == '"' && field.back() == '"')
            {
                field.remove_prefix(1);
                field.remove_suffix(1);
            }
            
            fields.push_back(field);
            start = end + 1;
        }
        
        return fields;
    }
};

void PracticalApplicationsDemo()
{
    std::cout << "=== Practical Applications Demo ===" << std::endl;
    
    // 日志解析示例
    std::cout << "1. Log Parser:" << std::endl;
    std::string logData = 
        "2023-10-01T10:30:00 INFO Application started\n"
        "2023-10-01T10:30:01 DEBUG Loading configuration\n"
        "2023-10-01T10:30:02 WARN Configuration file not found, using defaults\n"
        "2023-10-01T10:30:03 ERROR Failed to connect to database\n"
        "2023-10-01T10:30:04 INFO Retrying database connection\n";
    
    auto logEntries = LogParser::parseLog(logData);
    
    for (const auto& entry : logEntries)
    {
        std::cout << "  [" << entry.timestamp << "] " 
                  << entry.level << ": " << entry.message << std::endl;
    }
    
    // CSV解析示例
    std::cout << "\n2. CSV Parser:" << std::endl;
    std::string csvData = 
        "Name,Age,City\n"
        "\"John Doe\",30,\"New York\"\n"
        "Jane Smith,25,London\n"
        "Bob Johnson,35,\"Los Angeles\"\n";
    
    auto csvRows = CSVParser::parseCSV(csvData);
    
    for (size_t i = 0; i < csvRows.size(); ++i)
    {
        std::cout << "  Row " << i << ": ";
        for (size_t j = 0; j < csvRows[i].size(); ++j)
        {
            if (j > 0) std::cout << ", ";
            std::cout << "'" << csvRows[i][j] << "'";
        }
        std::cout << std::endl;
    }
    
    // 文本分析示例
    std::cout << "\n3. Text Analysis:" << std::endl;
    std::string text = "The quick brown fox jumps over the lazy dog. "
                      "This sentence contains every letter of the alphabet.";
    
    std::string_view textView = text;
    
    // 统计单词
    size_t wordCount = 0;
    size_t start = 0;
    while (start < textView.size())
    {
        // 跳过空白字符
        while (start < textView.size() && std::isspace(textView[start]))
        {
            start++;
        }
        
        if (start < textView.size())
        {
            // 找到单词结束
            size_t end = start;
            while (end < textView.size() && !std::isspace(textView[end]) && 
                   textView[end] != '.' && textView[end] != ',')
            {
                end++;
            }
            
            if (end > start)
            {
                wordCount++;
                auto word = textView.substr(start, end - start);
                if (wordCount <= 5) // 只显示前5个单词
                {
                    std::cout << "  Word " << wordCount << ": '" << word << "'" << std::endl;
                }
            }
            
            start = end;
        }
    }
    
    std::cout << "  Total words: " << wordCount << std::endl;
    std::cout << "  Text length: " << textView.length() << " characters" << std::endl;
}

int main()
{
    PerformanceTest::stringParameterTest();
    PerformanceTest::substringTest();
    PracticalApplicationsDemo();
    
    return 0;
}

总结

  1. std::string_view基础:C++17的轻量级字符串视图,不拥有数据,只提供访问
  2. 性能优势
    • 避免不必要的内存分配
    • 零拷贝字符串操作
    • 高效的子字符串创建
    • 统一的字符串接口
  3. 主要用途
    • 函数参数(接受任何字符串类型)
    • 字符串解析和分析
    • 临时字符串操作
    • 性能敏感的代码
  4. 注意事项
    • 悬空指针问题(底层数据被销毁)
    • 只读性质(不能修改内容)
    • 生命周期管理
    • 临时对象陷阱
  5. 最佳实践
    • 用作函数参数而非成员变量
    • 不要返回指向局部数据的string_view
    • 小心临时string对象
    • 用于解析而非存储
  6. 实际应用
    • 日志解析
    • CSV处理
    • 文本分析
    • 配置文件解析
    • 网络协议解析
updatedupdated2025-09-202025-09-20