3

I have the following code.

void print_pair(const std::pair<const std::string&, const int&>& p)
{
    std::cout << p.first << "," << p.second << std::endl;
}
print_pair(std::pair<const std::string&, const int&>("test",1));//1
print_pair(std::pair<const std::string&, const int&>(std::string("test"),1));//2

which produces the following output:

,1
test,1

shouldn't the two lines produce the same output, as in the first case the constructor for string from char* should be implicitly called? why does const reference not seem to prolong the life of first pair argument in the first case?

it is compiled with gcc4.9 -std=c++11 -O3.

3
  • Try removing the & from std::string... Commented Mar 21, 2015 at 3:32
  • Works for me. Commented Mar 21, 2015 at 3:37
  • 2
    @zenith: You have built in C++03 mode, where the best match for the constructor is std::pair<std::string const&, int const&>(std::string const &, int const &). Up until C++11, the temporary string would be created by the caller and it would outlive the function call. If you rerun that code in C++11 or C++14 mode you will get undefined behavior. Commented Mar 21, 2015 at 3:41

1 Answer 1

8

The problem is that your pair is a pair of references, not values. When you have:

using pair_t = std::pair<const std::string&, const int&>;
pair_t("test",1);

The compiler needs to find the best candidate for the construction, the best match in C++11 is:

template< class U1, class U2 >
constexpr pair( U1&& x, U2&& y );

Where the types are U1 = const char(&)[5] and U2 = int. Internally, to bind the reference it is going to create a temporary string, but when that expression completes (and before returning from that constructor), the temporary will go away and you will be left with a dangling reference.

The program has undefined behavior, and it prints an empty string in the same way that it could have crashed or print any garbage.

In the case where you do:

pair_t(std::string("test"), 1);

The expression in which the temporary is created is the same expression that calls the function, and the lifetime of that temporary will last until the function completes, so that second line is correct and exhibits the expected behavior.

Sign up to request clarification or add additional context in comments.

3 Comments

I didn't get this on a first reading. Hence upvoting after second reading. It's a pretty subtle breaking change in the standard. As far as I can see it's not listed in the compatibility section.
is string literal an lvalue and U1 should thus be char[5]&?
@swang: Yes, I did not pay enough attention to that detail, the deduced type would be const char (&)[5]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.