https://www.learncpp.com/cpp-tutorial/introduction-to-stdstring/
std::string
- can have flexible length, involves malloc, slower
- passing
std::string
by value causes a copy, so don’t
- use
std::string_view
or const std::string&
as parameter
- supports
move
semantics, return std::string
by value is fine
- doesn’t work well with
constexpr
(use string_view
) instead
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
#include <string>
int main()
{
std::string name { "Alex" }; // initialize name with string literal "Alex"
name = "Jason"; // change name to a longer string
name = "Jay"; // change name to a shorter string
size_t l = name.length(); // get length
return 0;
}
|
string literal
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int main()
{
using namespace std::string_literals; // access the s suffix
using namespace std::string_view_literals; // access the sv suffix
std::cout << "foo"; // null terminated c style string literal
std::cout << "bar"s; // std::string literal (with the suffix 's')
std::cout << "zaa"sv; // std::string_view literal (with the suffix 'sv')
// std::string literal is equivalant to
auto s = std::string {"bar", 3} ;
return 0;
}
|
std::string_view
(c++17)
- basically the rust slice
- provides read-only access to existing string (or another
string_view
)
- no copy
string_view
parameter can take a std::string
(implicit conversion), no
copy
- do not return a
string_view
if created from a local string
- not vice versa:
std::string_view
doesn’t implicitly convert to std::string
- can create a
std::string
with a std::string_view
initializer or
static_cast
a string_view
to string
- fully supports
constexpr
- prefer to use
constexpr std::string_view
for string symbolic constants
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <iostream>
#include <string>
#include <string_view>
int main()
{
// initialize with C-style string literal
std::string_view s1 { "Hello, world!" };
// initialize with std::string
std::string s{ "Hello, world!" };
std::string_view s2 { s };
// initialize with std::string_view
std::string_view s3 { s2 };
return 0;
}
|
string_view
lifetime
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
|
#include <iostream>
#include <string>
#include <string_view>
int main()
{
std::string_view sv{};
{
std::string s{ "Hello, world!" };
sv = s; // sv is now viewing s
} // s is destroyed here, so sv is now viewing an invalid string
std::cout << sv << '\n'; // undefined behavior
return 0;
}
int main2()
{
std::string s { "Hello, world!" };
// sv views s
std::string_view sv { s };
// modifies s, which invalidates sv (s is still valid)
s = "Hello, universe!";
// Viewing through sv is UB here
// revalidate sv
sv = s;
// viewing through sv is valid here.
return 0;
}
|
- do not initialize
std::string_view
from std::string
literal => dangling
string_view