bewilderex63
bewilderex63

Reputation: 437

Is it safe to pass an `std::string` temporary into an `std::string_view` parameter?

Suppose I have the following code:

void some_function(std::string_view view) {
    std::cout << view << '\n';
}

int main() {
    some_function(std::string{"hello, world"}); // ???
}

Will view inside some_function be referring to a string which has been destroyed? I'm confused because, considering this code:

std::string_view view(std::string{"hello, world"});

Produces the warning (from clang++):

warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]

What's the difference?

(Strangely enough, using braces {} rather than brackets () to initialise the string_view above eliminates the warning. I've no idea why that is either.)

To be clear, I understand the above warning (the string_view outlives the string, so it holds a dangling pointer). What I'm asking is why passing a string into some_function doesn't produce the same warning.

Upvotes: 6

Views: 3045

Answers (4)

Enlico
Enlico

Reputation: 28520

std::string_view is nothing other than std::basic_string_view<char>, so let's see it's documentation on cppreference:

The class template basic_string_view describes an object that can refer to a constant contiguous sequence of char-like objects with the first element of the sequence at position zero.

A typical implementation holds only two members: a pointer to constant CharT and a size.

The part I have highlighted tells us why clang is right about std::string_view view(std::string{"hello, world"});: as others have commented it's because after the declaration is done, std::string{"hello, world"} is destroyed and that underlying pointer that the std::string_view holds dangles.

Clearly that's just a typical implementation, but since we know it is correct, it tells us at least that the standard doesn't require any implementation to do something special to keep temporaries alive.

Upvotes: 5

mpro34
mpro34

Reputation: 106

Just as others have said, some_function(std::string{"hello, world"}); is totally safe since it passes it by value and stays in scope until the function ends. If safety is all you are concerned with, that will do, if performance could be an issue, I'll recommend using an rvalue reference here like so:

void some_function(std::string_view&& view)
{
    std::cout << "rval reference: " << view << '\n';
}

int main()
{
    some_function(std::string{"hello, world"});
}

R-value references are great if you are going to use some_function() mainly for temporary values.

Upvotes: 0

HolyBlackCat
HolyBlackCat

Reputation: 96934

some_function(std::string{"hello, world"}); is completely safe, as long as the function doesn't preserve the string_view for later use.

The temporary std::string is destroyed at the end of this full-expression (roughly speaking, at this ;), so it's destroyed after the function returns.


std::string_view view(std::string{"hello, world"}); always produces a dangling string_view, regardless of whether you use () or {}. If the choice of brackets affects compiler warnings, it's a compiler defect.

Upvotes: 8

eerorika
eerorika

Reputation: 238491

Is it safe to pass an std::string temporary into an std::string_view parameter?

In general, it isn't necessarily safe. It depends on what the function does. If you don't know, then you shouldn't assume it to be safe.

Knowing the definition of the function as shown, it is safe to call the example function with a temporary string.

Will view inside some_function be referring to a string which has been destroyed?

Not in this case, because the temporary argument string - which the string view refers to - hasn't been destroyed.


What's the difference?

The parameter of the function has shorter lifetime than the lifetime of the temporary passed as the argument. The lifetime of the string view variable is longer than the lifetime of the temporary argument passed to the constructor.

Upvotes: 1

Related Questions