Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a C string in a constexpr function: why no warning from the compiler?

Consider the following code:

constexpr auto f()
{
    auto str = "Hello World!";
    return str;
}

int main(int argc, char* argv[])
{
    static constexpr auto str = f();
    std::cout << str << std::endl;
    return 0;
}

Is that normal that my compiler does not display any warning? Is it defined behavior? Do I have the guarantee that the program will display "Hello World!"? I would expect the "Hello World!" not to live beyond the scope of the function...

like image 357
Vincent Avatar asked Jul 28 '17 06:07

Vincent


People also ask

Can a function return constexpr?

Unlike const , constexpr can also be applied to functions and class constructors. constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time.

Why does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Is constexpr implicitly static?

constexpr is a compile time feature, where inline/static are runtime features. The meaning of constexpr is more restricted than static. The meaning is that given a particular input value the return value is always the same, and the copiler ought to be able to work it out completely during compilation.

Can strings be constexpr?

constexpr std::string While it's best to rely on string_views and not create unnecessary string copies, the example above shows that you can even create pass vectors of strings inside a constexpr function!


2 Answers

In C++ string literals have static storage duration and live as long as the program runs. So, a pointer to a string literal returned from f is always valid. No allocation or deallocation is involved.

Note that string literals have type const char[N], which in your case decays to const char * due to auto type deduction. If your intent was to use std::string, you can directly construct it

auto str = std::string("Hello World!");

or use operator""s:

using std::string_literals;
auto str = "Hello World!"s;

However, since std::string is not a literal type, this values cannot be constexpr anymore.

like image 115
lisyarus Avatar answered Sep 19 '22 08:09

lisyarus


That's the second effect of auto. What you think it is, is not always what the compiler decides. This can leads to wrong programmer expectation - the rule is here compiler always win.

The fact here is that str is a const char * to a (static storage duration) string litteral. It can be fully determined at build time, so it is a valid constexpr.

like image 20
Serge Ballesta Avatar answered Sep 19 '22 08:09

Serge Ballesta