Choosing Read-Only Text Parameters in C++17: string_view vs string& vs char*
A decision guide for choosing read-only text parameter types in C++17: compare string_view, const string&, and const char* with a compact trade-off table, concrete example, and validation steps to verify zero allocations and detect dangling views.
16 Jul 2026, 11:34 UTC

The Decision
You need a function parameter that accepts string literals, std::string objects, and substrings without copying. The codebase targets C++17 or later, the callee does not take ownership, and call sites are performance-sensitive. The choice among std::string_view, const std::string&, and const char* determines allocation behavior, lifetime guarantees, and null-termination requirements.
Constraints
- C++17 minimum (for
std::string_view) - No ownership transfer; the function only reads
- Null termination not required unless calling C APIs
- Call sites must avoid hidden allocations
Option Comparison
| Option | Literal | std::string | Alloc for literal | Owns data | Null-terminated | Since |
|---|---|---|---|---|---|---|
std::string_view | yes | yes | no | no | no | C++17 |
const std::string& | yes (creates temporary) | yes | yes | yes (via temporary) | yes | C++98 |
const char* | yes | no (needs .c_str()) | no | no | yes | C++98 |
Trade-offs
std::string_view
Zero allocations for literals and std::string arguments. Accepts substrings via substr() without copying. The caller must ensure the underlying character buffer outlives the call—binding to a temporary std::string or short-lived expression creates a dangling view. Not implicitly null-terminated; passing to C functions requires an explicit copy into a std::string or a null-terminated buffer.
const std::string&
Guarantees lifetime through the callee because a temporary std::string is materialized for literals and lives until the end of the full expression. However, that temporary forces a heap allocation and copy for every literal argument. Use when the callee may store the reference or needs guaranteed null-terminated ownership.
const char*
Zero overhead and naturally null-terminated, making it the right choice for C interfaces. Cannot bind directly to std::string (callers must write .c_str()). Carries null-pointer risk and requires a length scan if the callee needs the size.
Concrete Implementation
#include <iostream>
#include <string>
#include <string_view>
void print(std::string_view sv) {
std::cout << sv << '\n';
}
int main() {
std::string s = "hello";
print("literal"); // no allocation
print(s); // no allocation
print(s.substr(0, 3)); // no allocation, views substring
}
Validation Steps
- Compile with warnings: Run
g++ -std=c++17 -Wall -Wextra -O2 example.cpp -o exampleon Linux/macOS orcl /std:c++17 /W4 example.cppon Windows (Developer Command Prompt). Confirm no warnings about temporaries or unused parameters. - Verify zero allocations for literals: Link against a tracing allocator or instrument
std::stringwith a custom allocator that increments a counter on construction. Run the program and assert the counter stays at zero for the literal andstd::stringcalls. - Detect dangling views: Compile a variant that stores a
string_viewfrom a localstd::stringbeyond its scope:
Run under AddressSanitizer:std::string_view dangling() { std::string local = "oops"; return local; // returns view into destroyed buffer }g++ -std=c++17 -fsanitize=address -O1 -g test.cpp -o test && ./test. Expect a heap-use-after-free report. - Confirm no
std::stringconstruction in assembly: Inspectg++ -std=c++17 -O2 -S example.cpp -o - | grep -c "std::__cxx11::basic_string". A count of zero for the call sites confirms the compiler elided temporary construction.
Limitations
std::string_viewdoes not extend lifetime; the caller owns the buffer lifetime.- Implicit conversion from
std::stringorconst char*tostring_viewcan hide lifetime mismatches at call sites. - If the callee eventually calls a C API expecting
const char*, a null-terminated copy is still required. - Pre-C++17 codebases cannot use
string_viewwithout a backport or boost dependency.
Decision Rule
Default to std::string_view for C++17 read-only text parameters when the call does not need null termination or storage. Use const std::string& when the callee may store the reference or needs guaranteed null-terminated ownership. Reserve const char* for C interfaces.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.