我有一个类List自动分配内存来存储项目列表.
它有一个析构函数来释放这个内存:
List::~List()
{
free(memory);
}
Run Code Online (Sandbox Code Playgroud)
这意味着,如果我创建一个new列表,我可以delete用来调用析构函数并释放内存.
一旦变量超出范围,也将调用析构函数,这几乎总是我想要的.例如:
int func()
{
List list;
list.push(...);
...
return 47;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我想返回该列表怎么办?
List func()
{
List list;
return list;
}
Run Code Online (Sandbox Code Playgroud)
我正好复制列表,因为它是按值返回的,并且没有太多要复制的数据(只有几个整数和一个指针).
但是,列表分配并具有指针的内存包含大量数据.
由于我返回列表,因此列表将与指向此数据的指针一起复制.
由于列表现在超出了范围,因此调用析构函数,释放指向该数据的指针,即使副本也有指针.
如何防止调用此析构函数?
1)通过创建一个复制构造函数可能有一个解决方案,但是,我不想这样做,因为那个指针上的所有数据都可能不得不被复制,这是浪费时间,暂时需要双倍的内存来被分配.
2)我知道我可以创建一个指针List* list并返回它,但我想避免为可能的情况下为该列表分配新内存的必要性,并且还想避免为指针浪费更多内存(8个字节或其他东西).
提前致谢,
大卫.
假设您正在使用C++ 11或更高版本,您只需创建一个移动构造函数,将旧列表留空.
为了避免类似的问题,您还需要删除复制构造函数,或者实际编写它以便可以复制您的类(不要担心;在返回值的情况下,编译器将使用移动构造函数或返回值优化).
通过将指针存储为大大简化了unique_ptr这将有助于确保您不会出错,并且意味着您不需要显式编写副本或移动构造函数.
如果你坚持使用前C++ 11,你就不能这样做,至少不会没有很小的存储空间惩罚.你需要使用一个引用计数指针boost::shared_ptr(用C++ 11将标准库添加到标准库中,但听起来你宁愿只移动语义),它只会在最后一个时释放内存一个人留下引用那个记忆.这使得复制,创建和销毁列表的速度稍慢(因为它需要检查/更新引用计数器),并且需要一些空间来存储计数,但与实际复制列表内容相比,这些成本相对较小.
请注意,在这种情况下,两个副本始终指向实际上相同的列表.如果更新一个"副本",另一个也会更新.这通常不是您的类的用户在C++中期望的行为.