0

I have a C++ questions want to ask.

In the header, I defined a struct as following:

struct ObjectType
{
    const int                                 id;
    const std::string&                        value;

    ObjectType(const int id, const std::string& value = ""):
                    id     (id)
                  , value  (value)
{

}

};

In the anonymous namespace, I defined three variables:

namespace {
    const ObjectType sample1   (0, "sample1");
    const ObjectType sample2   (1, "sample2");
    const ObjectType sample3   (2, "sample3");
}

Then in my unittest when I try to use the ObjectType, the value is always be NULL:

TEST(TestClass, test01)
{
   std::cout << sample1.value << std::endl; // => This is always empty
}

As I remember since I defined the struct field as const, it should extend the input lifetime. Then sample1.value should be printed. However it doesn't.. Anyone knows why it happens? Thanks!

Justin
  • 24,288
  • 12
  • 92
  • 142
Terry Zhang
  • 4,541
  • 8
  • 23
  • 29
  • 1
    Fix identation pls. This gives me anxiety. – Kostas Jul 08 '19 at 23:38
  • 2
    Possible duplicate of [Does a const reference class member prolong the life of a temporary?](https://stackoverflow.com/questions/2784262/does-a-const-reference-class-member-prolong-the-life-of-a-temporary) – Justin Jul 08 '19 at 23:38
  • @Justin I don't think putting something in a namespace makes it temporary – Kostas Jul 08 '19 at 23:40
  • 2
    @Kosta True, namespace-level globals are not temporaries. However, the `std::string`s constructed to construct the globals _are_ temporaries. – Justin Jul 08 '19 at 23:41
  • `"sample1"` isn't a `string`. It's a const character array that gets converted into a temporary `string`. That difference between this question and Justin's proposed dupe is the only reason I didn't vote to close. There may be a better duplicate. – user4581301 Jul 08 '19 at 23:42
  • 1
    @user4581301 The difference between implicit conversion used here, vs. the explicit conversion used in the proposed dup, is very minor. – 1201ProgramAlarm Jul 08 '19 at 23:53
  • @1201ProgramAlarm the different is nearly non-existent in language terms, but if you don't know that `"sample1"` isn't a `string` the answer is useless to you because you don't know WHY you got a temporary. Zeqing Zhang, is this what you mean: https://ideone.com/iQICO2 ? – user4581301 Jul 09 '19 at 01:42

1 Answers1

3

This is undefined behavior.

const ObjectType sample1   (0, "sample1");

Because the parameter to this class's constructor is a const std::string &, this constructs a temporary std::string object from a string literal, passes it to the constructor, and when the constructor returns the temporary object gets destroyed.

The constructor saves the reference to the temporary object as its class member. Unfortunately the temporary object gets destroyed before it's referenced later, resulting in undefined behavior.

This has nothing to do with namespaces.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148