我可以在不分配内存或复制数据的情况下构造对象吗?

sif*_*man 4 c++ constructor

考虑一个包含char特定顺序的简单成员变量的类'B' .

class B {
    char x1;
    char x2;
    char x3;
    char x4;
}
Run Code Online (Sandbox Code Playgroud)

我有一个缓冲区A已经包含与中定义的顺序相同的数据B.另一个进程已经加载A了数据.

char A[4];
Run Code Online (Sandbox Code Playgroud)
  1. 是否有可能构造一个B包含数据的类型的对象A,而没有构造函数复制数据?也就是说,我想将一个B对象"覆盖" 到A缓冲区上,这样我就可以B在数据上使用方法,而不会产生副本的开销或内存的分配.

  2. 假设有一个问题1的解决方案,是否有任何理由我不能定义一个D派生自的类,B哪个方法引用成员变量B,但它本身不包含新的成员变量?

Ser*_*eyA 6

尽管不愉快,但没有法律(标准)方法来实现这一目标.相反,你有一个非法的,但通常是工作的(用于过多的地方)或合法的,但优化依赖.

无论方法如何,这都假设B成员没有填充(添加[[gnu::packed]]gcc,或者编译器的其他内容为B定义,以确保不会发生填充).

首先是非法的 - 您可以为该类型添加别名.这违反了严格的别名规则,但已知可以在许多平台和编译器上运行.代码示例:

const B* b = reinterpret_cast<const B*>(&a[0]);
Run Code Online (Sandbox Code Playgroud)

第二种选择是依赖编译器的优化器.它通常足够强大,可以实现不需要实际复制数据,并且只使用原始值.它不会一直发生,如果您在性能关键部分依赖此技术,则最好检查生成的代码并在每次编译器升级时重新检查它.

此代码假定优化:

B b;
memcpy(&b, &a[0], sizeof(b));
// use b in non-modifying way
// Compilers usually will not issue a copy here, YMMV
Run Code Online (Sandbox Code Playgroud)


Nat*_*ica 6

既然一个A不是一个B没有合法的方式来对待A一个B.也就是说,如果A是一个标准的布局类,那么你应该能够投射它并且它将"工作"但它不合法.例如

struct A
{
    char data[6] = "hi 0/";
    int a = 10;
    int b = 20;
};

struct B
{
    char x1;
    char x2;
    char x3;
    char x4;
    char x5;
    char x6;
};

std::ostream& operator <<(std::ostream& os, B& b)
{
    return os << b.x1 << b.x2 << b.x3 << b.x4 << b.x5 << b.x6;
}

int main()
{
    A a;
    B* b = reinterpret_cast<B*>(&a);
    std::cout << *b;
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为数组和成员在每个类中占用相同的内存部分,但这不能保证.有可能是填充后x1B这意味着不是所有成员将被映射到阵列.

现在,如果你重新设计B一个数组而不是像单独的成员那样

struct A
{
    char data[6] = "hi 0/";
    int a = 10;
    int b = 20;
};

struct B
{
    char data[6];
};
Run Code Online (Sandbox Code Playgroud)

然后你可以使用一个联盟来保持两者A并且B因为它B具有相同的共同初始序列,因为A它是合法使用的b.这可能看起来像

union Converter
{
    Converter() : a{} {}
    A a;
    B b;
};

std::ostream& operator <<(std::ostream& os, B& b)
{
    return os << b.data;
}

int main()
{
    Converter c;
    std::cout << c.b;
}
Run Code Online (Sandbox Code Playgroud)

现在,演员阵容已经消失,我们从标准得到保证,这是安全的

  • 很好地提醒了常见的初始序列规则. (2认同)
  • @SergeyA谢谢.它看起来可能是OP可以使用的东西 (2认同)