How to use Strings way to quick briefing

How to use Strings (way to quick briefing) Jason Kenny

Overview • Current issues • std: : string_view and std: : string • C interfaces • What about all these other string objects?

What are the current problems? • Current logic has unclear ownership rules. • Do you delete or not? • Difficult to return new strings without leaking small about of memory • We often make un-needed copies and memory allocations • We are doing extra strlen() calls when we don't have to

Examples: Core issue char* function(. . . ) char *v 1 = function(); Do we need to delete v 1? class obj { char* method(. . . ) } Obj myobj; . . . char *v 2 = myobj. method(); Do we need to delete v 2?

std: : string • Owns memory • Never leaks • Can reserve memory to avoid memory allocation • Via reserve() • Assignments will copy data in to string • This does not always mean we have to alloc • Small strings don't need to alloc any memory • Larger strings are based on capacity() of the string • Always know the size()length() in constant time • On function returns move symantecs allow memory to move/transfer between objects. • Ends with a Null terminator for C interface compatibility.

std: : string_view • Does not own memory • Points to a range of original string • Always know the size()length() in constant time • String is immutable ( unless you cheat with const_cast) • Range pointed to is mutable.

Pass by reference Do: Function (std: : string const &str) {} Function (std: : string &str) {} Function (ts: : string_view &sv) {} Don’t do: Function (std: : string str) {} Avoid: Function (ts: : string_view str) {}

Return values OK: std: : string const& Myclass: : foo() Better: ts: : string_view Myclass: : foo()

Making temporary string Existing code: char * layout_relative(const char *root, const char *file) { char path[PATH_NAME_MAX]; . . . return ats_strdup(path); // copy string (malloc and string copy. May Leak) } New Way std: : string layout_relative(ts: string_view const &root, char ts: string_view const &file) { char path[PATH_NAME_MAX]; . . . std: : string ret(path); // copy string return path; //no leaking!! }

Interface with C interfaces ( wants char*) Prefer C interfaces with pointer and length as input ie : c_func(char *, size_t length) With std: : string: c_func(s. c_str(), s. length()); With std: : string_view: c_func(s. data(), s. length());

Interface with C interfaces - Continue • Sometimes we have C API that only take char* and no size. • Assume NULL terminator With std: : string: c_func(s. c_str()); // Has NULL terminator

Interface with C interfaces - Continue WARNING!! std: : string_view: c_func(sv. data()); // Make not have NULL terminator Make it safe: (unless you know for sure the object is at the end) std: : string tmp(sv. data(), sv. length()); c_func(tmp. c_str()); Can also say: ( can blow the stack, but avoids an possible alloc) char tmp[sv. length+1]; sv. copy(tmp, sv. length()); c_func(tmp. c_str());

Conclusion • Use std: : string: • To be the “owner” of the string data • For mutable operations • Use std: : string_view • In case in which we need a immutable copy. • Pass substrings • • Clear ownership intent in the API This will prevent memory leaks by mistake Will be as fast as char* ( no extra copies, or memory allocs) No need to call strlen() everywhere
- Slides: 13