Reputation: 1021
I've encountered a strange behavior about C++17 static inline member data
.
There is Implementation
abstract class:
class Implementation
{
public:
virtual void call() = 0;
};
There are Example
and AnotherExample
classes that implement the abstract class:
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;
}
};
Finally there is Implementer
class to use Example
and AnotherExample
classes:
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;
}
};
Using:
Implementer::get_example(true)->call(); // This expect to return example.
Implementer::get_example(false)->call(); // This expect to return another_example.
We expect to see this:
Called Example::call function!
Called AnotherExample::call function!
but we see this:
Called AnotherExample::call function!
Called AnotherExample::call function!
I don't understand it. How does example
object get the value of another_example
object?
Edit: We can get desired output if we change
static inline Implementation* example = unique_ptr<Example>(new Example).get();
to
static inline unique_ptr<Implementation> example = unique_ptr<Example>(new Example);
Upvotes: 2
Views: 88
Reputation: 18864
The unique_ptr<Example>(new Example).get()
would destroy the new Example
instance as soon as the result of get()
gets assigned (thanks @JVApen for correcting).
From that point on a whole lot of strange things may happen.
For instance, the object allocated by new AnotherExample
can (and most probably will) be placed to the same memory where the first one was, and the first pointer would suddenly point to a valid live object again.
Not sure if this qualifies as an ABA phenomenon, but what happens is very similar -- you think you are looking at A, but it's a different A.
I'd first clean it up under Valgrind or ASAN.
Coliru sandbox here
Upvotes: 5