我有一个存储多维数组作为成员的类。
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();
那样在堆上分配对象并返回指针会改变什么呢?
答案 0 :(得分:3)
按值返回对象时,将复制实际数据(32 3 int
s)。编译器可能会优化副本(所谓的“复制省略”),但这绝不保证。
如果动态分配对象并返回指向它的指针,当然不会有复制。如果您有权访问C ++ 11,请考虑返回std::unique_ptr
,以便明确所有权,并且不存在内存泄漏的可能性。
在C ++ 11中,您还可以通过将成员Data
转换为一个内容(例如std::vector
)来“做得更好”,该内容将其数据内部存储在堆上并具有移动语义。这意味着从函数返回时,将移动容器而不是复制容器,并且不会复制数据。
答案 1 :(得分: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;
}
答案 2 :(得分:0)
你可以按照自己的意愿行事。如果你定义这样的函数......
Structure* someFunction();
将返回指向Structure对象的指针。必须使用new分配此对象。例如,定义这样的函数:
Structure* someFunction() {
Structure* someNewStructure = new Structure();
return someNewStructure;
}
你必须记住,这个元素是在这个函数中创建的,并且该函数正在将“对象”转移到将此对象销毁给调用者。通常最好避免这种情况,尽管它具有大型数据结构。处理此问题的另一种方法是在类中定义复制构造函数,以便您可以按引用的方式执行此操作。如果您这样做,则不定义此复制构造函数:
Sturcture someFunction() {
Structure someResultStruct;
return someResultStruct;
}
在这种情况下调用someFunction时,如果您的类包含动态元素或其他复杂数据类型,则无法保证在返回时正确复制它们,并且您将获得奇怪的行为......除非您定义自己的复制构造函数