1

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

struct Structure
{
    Structure()
    {
        memset(Data, 0, sizeof Data);
    }

    int Number;
    int Data[32][32][32];
}

当我编写一个返回 this 对象的函数时Structure,如果Data成员复制了所有字节,还是只是传递了一个引用?

Structure Create(int Parameter)
{
    Structure structure;

    // modify structure based on parameter
    // ...

    return structure;
}

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

4

3 回答 3

3

当您按值返回对象时,将复制实际数据(32 3 s)。 int编译器可能会优化掉副本(所谓的“复制省略”),但这永远不能保证。

如果你动态分配对象并返回一个指向它的指针,当然不会有复制。如果您有权访问 C++11,请考虑返回 a std::unique_ptr,以便所有权明确并且没有内存泄漏的机会。

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

于 2013-05-17T15:34:10.810 回答
1

当您按值返回对象时,该对象实际上不会被复制,而是您的函数将直接在调用者内存中填充该对象。就好像您执行了以下操作:

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;
}
于 2013-05-17T15:34:28.527 回答
0

你可以让它随心所欲。如果你定义一个这样的函数......

Structure* someFunction();

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

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

您必须记住,此元素是在此函数中创建的,并且该函数正在将销毁此对象的“责任”转移给调用者。通常最好避免这种情况,但对于大型数据结构则不能。处理这个问题的另一种方法是在你的类中定义一个复制构造函数,这样你就可以按照你引用的方式来做。如果您这样做,则无需定义此复制构造函数:

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

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

于 2013-05-17T15:35:41.797 回答