Commit e339f259 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

String view notebook: one correction, and the copyright notice has been...

String view notebook: one correction, and the copyright notice has been modified as it is entirely new content.
parent 31bb1758
%% Cell type:markdown id:451d5c67-1c82-4f19-9fd4-b7dd49bac7fb tags:
# [Getting started in C++](./) - [Stringview](./StringView.ipynb)
%% Cell type:markdown id:bd83674b-5f88-4d28-b959-ba315588fa67 tags:
C++ 17 introduced `std::string_view`, which basically introduces a sort of viewer over a string (not especially a `std::string`: it works basically as long as it's a chain of contiguous characters, where what is a *character* is defined as first template argument).
C++ 17 introduced `std::string_view`, which is basically a sort of viewer over a string (not especially a `std::string`: it works basically as long as it's a chain of contiguous characters, where what is a *character* is defined as first template argument).
Let's roll an example to illustrate how it works:
%% Cell type:code id:d6cc7d26-80ba-4c0a-a276-56f9d850bbbe tags:
``` C++17
#include <string>
#include <string_view>
#include <iostream>
void print(std::string_view content)
{
std::cout << "Content is '" << content << "'" << std::endl;
}
std::string hello("Hello world from std::string!");
print(hello);
print("Hello world!");
```
%% Cell type:markdown id:e565e634-7abb-403a-af47-b46e7e9936e5 tags:
Prior to C++ 17, the usual way was to use `const std::string&` as parameter (passing a `std::string` directly would incur copies):
%% Cell type:code id:f1562c99-1b25-4314-9903-1932571fe86d tags:
``` C++17
#include <string>
#include <iostream>
void print_with_const_ref(const std::string& content)
{
std::cout << "Content is '" << content << "'" << std::endl;
}
std::string hello("Hello world from std::string!");
print_with_const_ref(hello);
print_with_const_ref("Hello world!");
```
%% Cell type:markdown id:4df1c364-df85-4a4d-a0d3-43218189354d tags:
So what did we gain exactly in the bargain?
If you remember the discussion about *l-values* and *r-values* in the [notebook about move semantics](../5-UsefulConceptsAndSTL/5-MoveSemantics.ipynb), the construct used prior to C++ 17 doesn't necessarily make much sense: in our second call the argument `Hello world!` is clearly a r-value whereas a l-value would be expected given the prototype!
%% Cell type:markdown id:414b36fb-0179-4a0f-a963-2c931c93e12a tags:
Let's write the same *without* the `const` to convince ourselves:
%% Cell type:code id:b7471040-bffb-4a48-8ea0-2ad1fddbf442 tags:
``` C++17
#include <string>
#include <iostream>
void print_with_ref(std::string& content)
{
std::cout << "Content is '" << content << "'" << std::endl;
}
print_with_ref("Hello world!"); // COMPILATION ERROR!
```
%% Cell type:markdown id:f9dc26d5-1b95-4c75-8ca8-901e6962215e tags:
This time it doesn't work at all...
So when we provide a r-value argument to a `const std::string&` parameter, the compiler does some magic to interpret it. This magic is not without cost: a `std::string` is allocated on the fly to store the content of the r-value.
That is what `std::string_view` strives to correct: when it is used there are no such allocation involved.
So whenever possible, using `std::string_view` instead of `const std::string&` is advised - provided of course your project is firmly grounded in C++ 17 or later.
That doesn't mean there are no costs involved: when you are using `std::string_view`, you are essentially taking the responsability to ensure the memory area still exists (very similarly to the kind of contract you pass when you define a reference). [CppReference](https://en.cppreference.com/w/cpp/string/basic_string_view) illustrates this on a very basic case:
%% Cell type:code id:157f9843-02d4-4c7b-b062-f4403f911cd8 tags:
``` C++17
// Beware: the code in this cell seems to disturb Xeus-cling ability to write to std::cout...
// A ticket has been emitted: https://github.com/jupyter-xeus/xeus-cling/issues/405
#include <iostream>
#include <string>
#include <string_view>
std::string_view bad(std::string("a temporary string")); // "bad" holds a dangling pointer
// Any use of bad here will result in undefined behaviour as the `std::string` was destroyed in
// previous line when it went out of scope!
```
%% Cell type:markdown id:d8be6dd3-6ecf-4861-a556-35fe159e3445 tags:
C++ 20 will expand on this possibility for other contiguous containers with [`std::span`](https://en.cppreference.com/w/cpp/container/span).
%% Cell type:markdown id:d46d567d-50e9-4fef-a689-deaaff8d059a tags:
© _CNRS 2016_ - _Inria 2018-2021_
_This notebook is an adaptation of a lecture prepared by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
_The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_
© _Inria 2021_
_This notebook is released under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment