简体   繁体   中英

C++17 and reference extension of static temporary lifetime

I have some code which is trying to do a kind of singleton polymorphism, like so:

// header
struct B
{
    virtual ~B() = default;
    virtual void F() = 0;

    static const B& Type1;
    static const B& Type2;
};

// cpp
struct D1 : B
{
    void F() override;
};

struct D2 : B
{
    void F() override;
};

const B& B::Type1 = D1();
const B& B::Type2 = D2();

// consumer
class Usage
{
public:
    Usage() : m_b(&B::Type1) {}

    void UseType1() { m_b = &B::Type1; }
    void UseType2() { m_b = &B::Type2; }
    void F() const { m_b->F(); }
private:
    const B* m_b;
};

Thus the consuming class always uses one of these instances, but the specific one is decided at runtime. (It's using references for polymorphism at the top level rather than pointers in order to properly delete the objects, but also avoid putting them on the heap as a smart pointer would.)

As I understand it, a const reference to a temporary is supposed to extend the lifetime of that temporary for the lifetime of the reference (with some caveats about lifetime generally ending at function exit or something like that). Since these particular references have static scope, they should exist for the lifetime of the process and thus keep the temporary around that long as well.

This code works as expected in VS2015, and also in VS2017 15.8.5 in the default C++14 compilation mode.

However, if I switch VS2017 to the C++17 compilation mode, then (without any compiler warnings) this crashes at runtime because some particular const B* points to an object which has a completely unrelated vtable -- ie. something has stomped on the memory which was supposed to be reserved for one of the instances. I assume that this means that the temporary was destroyed too early.

I can make this behave as expected by avoiding use of a temporary:

static const D1 GlobalType1;
static const D2 GlobalType2;
const B& B::Type1 = GlobalType1;
const B& B::Type2 = GlobalType2;

Is this a compiler bug or a standards violation in the code?

Since the conclusion in the comments seems to be that this is indeed a compiler bug, I've reported an issue .

Leaving the question open for a little while longer until this is concluded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM