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

问题描述 投票:2回答:1

我遇到了关于C++17 static inline member data的奇怪行为。有Implementation抽象类:

class Implementation
{
public:
  virtual void call() = 0;
};

有实现抽象类的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;
  }
};

最后有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;
  }
};

使用中:

Implementer::get_example(true)->call(); // This expect to return example.
Implementer::get_example(false)->call(); // This expect to return another_example.

我们希望看到这个:

Called Example::call function!
Called AnotherExample::call function!

但是我们看到了:

Called AnotherExample::call function!
Called AnotherExample::call function!

我听不懂。 example对象如何获取another_example对象的值?编辑:如果我们进行更改,我们将获得所需的输出

static inline Implementation* example = unique_ptr<Example>(new Example).get();

to

static inline unique_ptr<Implementation> example = unique_ptr<Example>(new Example);
c++ c++11 pointers memory-management
1个回答
5
投票

unique_ptr<Example>(new Example).get()将在分配了Example的结果后立即销毁新的get()实例(感谢@JVApen进行纠正)。

从那以后可能会发生很多奇怪的事情。

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

[不确定这是否可以视为ABA现象,但是发生的情况非常相似-您认为您正在看的是A,但它是不同的A。

我首先要在ValgrindASAN下清理它。

Coliru沙箱here

© www.soinside.com 2019 - 2024. All rights reserved.