C++:初始化成员数据时的奇怪行为

İbr*_*him 2 c++ pointers memory-management c++11

我遇到了一个关于C++17 static inline member data.
Implementation抽象类:

class Implementation
{
public:
  virtual void call() = 0;
};
Run Code Online (Sandbox Code Playgroud)

ExampleAnotherExample实现抽象类的类:

class Example : public Implementation
{
public:
  void call() override
  {
    cout << "Called Example::call function!" << endl;
  }
};

class AnotherExample : public Implementation
{
public:
  void call() override
  {
    cout << "Called AnotherExample::call function!" << endl;
  }
};
Run Code Online (Sandbox Code Playgroud)

最后是Implementer要使用的类ExampleAnotherExample类:

class Implementer
{
private:
  static inline Implementation* example = unique_ptr<Example>(new Example).get(); // or make_unique<Example>().get()
  static inline Implementation* another_example = new AnotherExample;
public:
  static Implementation* get_example(bool flag)
  {
    // This function returns example object if flag is true otherwise another_example object.
    if (flag)
      return example;
    else
      return another_example;
  }
};
Run Code Online (Sandbox Code Playgroud)

使用:

Implementer::get_example(true)->call(); // This expect to return example.
Implementer::get_example(false)->call(); // This expect to return another_example.
Run Code Online (Sandbox Code Playgroud)

我们希望看到这一点:

Called Example::call function!
Called AnotherExample::call function!
Run Code Online (Sandbox Code Playgroud)

但我们看到了这一点:

Called AnotherExample::call function!
Called AnotherExample::call function!
Run Code Online (Sandbox Code Playgroud)

我不明白。exampleobject是如何获取object的值的another_example

编辑:如果我们改变,我们可以获得所需的输出

static inline Implementation* example = unique_ptr<Example>(new Example).get();
Run Code Online (Sandbox Code Playgroud)

static inline unique_ptr<Implementation> example = unique_ptr<Example>(new Example);
Run Code Online (Sandbox Code Playgroud)

bob*_*bah 5

unique_ptr<Example>(new Example).get()会破坏新Example尽快实例作为结果get()被分配(@JVApen纠正感谢)。

从那时起,可能会发生很多奇怪的事情。

例如,由分配的对象new AnotherExample可以(并且很可能会)被放置到第一个所在的同一内存中,并且第一个指针会突然再次指向一个有效的活动对象。

不确定这是否属于ABA现象,但发生的情况非常相似——你认为你在看 A,但它是一个不同的 A。

我首先在ValgrindASAN下清理它。

Coliru沙箱在这里

  • 实际上,当 get 返回时,该值仍然有效。只有在序列点(读为 ; ),临时变量才会超出范围。因此,分配将首先发生,然后 unique_ptr 超出范围。 (2认同)