在复制具有巨大数组成员的类时使用

Are pointers used when copying a class with huge array member?

本文关键字:组成员 数组 复制 巨大      更新时间:2023-10-16

我有一个存储多维数组的类作为成员。

struct Structure
{
    Structure()
    {
        memset(Data, 0, sizeof Data);
    }
    int Number;
    int Data[32][32][32];
}

当我写一个函数返回这个Structure的对象时,如果Data成员复制或只是传递引用,那么所有字节都是复制的吗?

Structure Create(int Parameter)
{
    Structure structure;
    // modify structure based on parameter
    // ...
    return structure;
}

如果这导致复制整个数据块,我如何做得更好?在堆上分配像Structure *structure = new Structure();这样的对象并返回该指针会发生什么变化?

按值返回对象时,将复制实际数据(323 int s)。编译器可能会优化删除副本(所谓的"副本省略"),但这不能保证。

如果动态分配对象并返回指向它的指针,当然不会进行复制。如果您可以访问c++ 11,请考虑返回std::unique_ptr,以便所有权清晰,并且没有内存泄漏的机会。

在c++ 11中,您还可以通过将成员Data转换为容器(如std::vector)来"做得更好",该容器内部将其数据存储在堆上并具有move语义。这意味着当从函数返回时,容器将被移动而不是复制,并且数据不会重复。

当您按值返回一个对象时,该对象实际上不会被复制,相反,您的函数将直接在调用者内存中填充该对象。就好像你做了以下事情:

Structure s;
Create(Parameter, &s);

虽然稍微好一点,因为默认构造函数甚至不会被调用。这被称为"返回值优化"。虽然它不受标准的保证,但它被所有主流的c++编译器(clang, gcc和Visual c++都包括在内)执行。

如果你想把它放在堆上,那么这样做:

Structure * Create(int Parameter)
{
    Structure * structure = new Structure();
    return structure;
}

但是最好使用智能指针。如果你使用c++11,你可以使用std::unique_ptr .

std::unique_ptr<Structure> Create(int Parameter)
{
    auto structure = std::unique_ptr<Structure>(new Structure());
    return structure;
}

你可以让它按照你想要的方式运行。如果你像这样定义一个函数…

Structure* someFunction();

将返回一个指向结构对象的指针。该对象必须分配new。例如像这样定义函数:

Structure* someFunction() {
    Structure* someNewStructure = new Structure();
    return someNewStructure;
}

你必须记住,这个元素是在这个函数中创建的,这个函数把销毁这个对象的"责任"转移给了调用者。通常最好避免这种情况,但对于大型数据结构则不能这样做。处理此问题的另一种方法是在类中定义复制构造函数,以便您可以按照引用的方式进行操作。如果您这样做而不定义复制构造函数:

Sturcture someFunction() {
    Structure someResultStruct;
    return someResultStruct;
}

当你在这种情况下调用someFunction时,如果你的类包含动态元素,或者其他复杂的数据类型,它们不能保证在返回时正确复制,你会得到奇怪的行为…除非你定义了自己的复制构造函数