C++ Weekly - Ep 271 - string.clear() vs string = ''

preview_player
Показать описание
☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟

T-SHIRTS AVAILABLE!

WANT MORE JASON?

SUPPORT THE CHANNEL

GET INVOLVED

JASON'S BOOKS

► C++23 Best Practices

► C++ Best Practices

JASON'S PUZZLE BOOKS

► Object Lifetime Puzzlers Book 1

► Object Lifetime Puzzlers Book 2

► Object Lifetime Puzzlers Book 3

► Copy and Reference Puzzlers Book 1

► Copy and Reference Puzzlers Book 2

► Copy and Reference Puzzlers Book 3

► OpCode Puzzlers Book 1


RECOMMENDED BOOKS

AWESOME PROJECTS

O'Reilly VIDEOS

Рекомендации по теме
Комментарии
Автор

Not sure why you're looking at libstdc++'s C++03 implementation of std::basic_string::clear()
The C++11 implementation does this:
void
clear() _GLIBCXX_NOEXCEPT
{ _M_set_length(0); }

Also, enable optimisations in compiler explorer so that inlining happens.

MalcolmParsons
Автор

Initially you would want to use the assignment. Then on a second release you replace them with the clear. The customer will be amazed by your optimizing skills!

jhbonarius
Автор

Another plus about functions like .clear() vs setting to empty string and .empty() vs checking for empty string, is that you don't have to find out the string type (wide, u8, etc) and that you can switch easier at a later time to a different type of string without having to change all your empty string literals related to those.

pantouffle
Автор

I think the relevant part here is the "Notes" section on cppreference:

"Unlike for std::vector::clear, the C++ standard does not explicitly require that capacity is unchanged by this function, but existing implementations do not change capacity. This means that they do not release the allocated memory"

This is NOT what I would expect .clear() to do. If I store a giant amount of data in std::string and call clear(), it's going to stay in memory. I don't really like that.

Spirrwell
Автор

After we all finish replacing all instances of = "" to .clear(), they implement an optimization that makes = "" 2x faster XD

DamianReloaded
Автор

Another advantage of .clear() is that the clear() method is noexcept, which can be helpful sometimes for small "reset" methods (not in the sample shown by Jason as there are other string objects allocated in that method).

vbaderks
Автор

In stl, if there is a member function to do a specific job, you should always consider it first.

hanyanglee
Автор

Looks like an old implementation of GCC string with ref counting, in that case all that is required, if not go direct to zero length. In theory it could const fold and constexp everything and just end up with the zeroing as zero can't be greater than capacity. As could the ="" being a literal, could constexp to set string to zero length.

surters
Автор

This is what I expect. The assignment operator has to cope with a potentially millions of characters on the RHS, therefore a RHS of "" is s special case for the assignment operator.
It is no surprise to find that the assignment operator is heavy duty as it has to cope with RHS's that can be any amount of characters, even none.

In contrast, for string.clear(), the vendor knows how string is implemented underneath, therefore they can do whatever valid C++ shortcuts to bring the string to the empty state.
And Jason has not done a video clip, but I say

std::vector.clear();
std::deque.clear();
std::list.clear();
std::forward_list.clear();
std::map.clear();
std::muttimap.clear();
std::set.clear();
std::muttiset.clear();
std::unordered_map.clear();

std::unordered_set.clear();


will likely be the cheapest, fastest way of emptying a container, therefore use it.
Similarly calling the empty() method will be the cheapest to determine if the container is empty (rather than size() == 0, which does not exist for forward_list).

One more thing on map, multimap, set and multiset's version of clear(). Yes the container could do erase(begin(), end()) or do a loop that erases an element at a time.
And many programmers know that underneath the hood they are implemented as Red-Black Trees.
If you erased 1-element at a time, the Red -Black tree has to rearrange it's nodes to maintain the Red-Black Tree properties.

Well many vendors have special cased the clear() in this case. They recursively just delete the nodes and don't bother maintaining the Red-Black Tree properties. Afterwards the container is set into an empty state. This is a much faster implementation of clear()

I also think the ISO C++ standard should be adjusted so that the container adapters queue(), priority_queue() and stack() also have a clear() which would forward the call to the underlying clear() of the container. This makes the container adapters easier to use.

stephenhowe
Автор

As I suspected, if you use a ""s literal, the assignment version is the same (or slightly better if you make the function noexcept).

Nobody
Автор

Even if we don't look at the code, it makes sense clear() is faster, since the intent of clear() is clearer and more specific, thus much narrower in scope, allowing it to be designed to do only the necessary for clearing the string -- as opposed to the assignment, which is much more vague

Автор

I love your videos (and podcast, of course). Thank you for being awesome!

Samossam
Автор

Great episode. Love the deep dive into a seemingly simple topic.

goobensteen
Автор

Let's do some math. By the moment of this comment, this video was watched by 10 000 people. It's 11:35 long. Average cpu speed is 4.4 GHz. Difference is 14 cpu cycles. So, to save the time, this video spent, it is necessary .clear() to be run = 2.17e15 times. That's 300 000 per person on earth. And I didn't take into account the time needed to type .clear() in source code.

luck
Автор

I would always use "" as it's more readable. .Clear() means container. "' means a string.
Even more, gcc already generates identical code in c++20 with -O3

etopowertwon
Автор

While I do prefer .clear to = "" I do not agree with the statement that the intent is clearer as long as somebody could mix up .empty with .clear. Luckily since C++20 it should not be possible since [[no discard]] was added

petermuller
Автор

Since different implementations may do the clear on linear time or constant time, it would have been interesting to see the test on different compilers/libs to see if there is a best combination.

fcolecumberri
Автор

With stuff like the assignment I‘d already be suspicious that it _might_ cost me an allocation (for a temp value), so from the get go I‘d probably lean towards .clear() anyway.

Runoratsu
Автор

In my last project I was wondering the best way to "empty" a string. Having started programming in C++ in the early 2000s and then taken a 15 year or so break, I've missed a lot of updates to the language and so missed .clear() and was wondering if .empty() was faster than ="". But I wonder what the memory implications of .clear() are. Although you'd probably have to have a lot of very large strings for it to make an impact on RAM usage.

axelBr
Автор

It is interesting to see how created_string = {} will perform. In any case this case is much better suited for optimization then "". IIRC the QString implementation for example uses a known "null-string" constant when default constructed. In that case there is no need to do normal string assignment.

YourCRTube