gpt4 book ai didi

c++ - 如何使用虚拟方法为具有非平凡成员的匿名 union 编写 operator=

转载 作者:可可西里 更新时间:2023-11-01 16:47:07 24 4
gpt4 key购买 nike

C++11 使我们能够创建具有非平凡成员的匿名 union 。这有时非常有用——例如,如果我想为一些没有默认构造函数的重要对象创建 Holder 类。
让我们通过给它一个虚拟方法来使这个 NonTrivial 对象更有趣:

#include <stdint.h>
#include <stdio.h>

struct Base
{
virtual void something() { printf("something\n"); }
};

struct NonTrivial : Base
{
explicit NonTrivial( int ) : a(1), b(2), c(3), d(4) { printf("NonTrivial\n"); }

virtual void something() override { printf("something non trivial\n"); }

int a;
int b;
int c;
int d;
};

struct Holder
{
Holder() : isNonTrivial(false), dummy(0x77) {}

Holder( NonTrivial n) : isNonTrivial(true), nonTrivial( n ) {}

bool isNonTrivial;
union
{
int dummy;
NonTrivial nonTrivial;
};

Holder & operator=( const Holder & rhs )
{
isNonTrivial = rhs.isNonTrivial;

if( isNonTrivial )
nonTrivial = rhs.nonTrivial;

return *this;
}
};

int main() {

Holder holder_1;
NonTrivial n(1);

Holder holder_2( n );

holder_1 = holder_2;

holder_2.nonTrivial.something();
holder_1.nonTrivial.something();

return 0;

}

这很管用。但是,这有效,因为编译器实际上并不在这里进行虚拟调用。让我们强制它:

Base * ptr = &holder_1.nonTrivial;

ptr->something();

这会产生段错误。
但为什么?我或多或少做了一件显而易见的事情——检查 holder 是否持有一个非平凡的对象,如果是——复制它。
阅读程序集后,我发现此 operator= 实际上并未从 rhs.nonTrivial 复制 vtable 指针。我假设发生这种情况是因为 NonTrivial 的 operator= 应该只在完全构造的对象上调用,并且完全构造的对象应该已经初始化了它的 vtable 指针 - 那么为什么要复制它呢?

问题:

  1. 我的想法正确吗?
  2. operator= 应该是什么样的创建 nonTrivial 对象的完整拷贝?我有两个想法 - 删除operator= 完全强制用户使用复制构造函数 - 或者使用placement new 而不是 nonTrivial = rhs.nonTrivial - 但也许还有其他选择吗?

附言我知道 std::optional 等,我正在尝试了解如何自己做。

最佳答案

如果有人在寻找快速答案时偶然发现这个问题,以下是我如何使用 placement new 解决此问题的方法:

template< typename T, typename ... Args >
void inplace_new( T & obj, Args && ... args )
{
auto * t = &obj;

t = new(t) T{ args... };
}

Holder & operator=( const Holder & rhs )
{
isNonTrivial = rhs.isNonTrivial;

if( isNonTrivial )
inplace_new( nonTrivial, rhs.nonTrivial );

return *this;
}

别忘了 #include <new> :)

关于c++ - 如何使用虚拟方法为具有非平凡成员的匿名 union 编写 operator=,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52820803/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com