【发布时间】:2024-01-19 00:14:01
【问题描述】:
我遇到了 std::unique_ptrs(特别是 MSFT VS 10.0 的实现)的问题。当我创建它们的 std::list 时,我使用的内存是创建仅包含底层对象的 std::list 时的两倍(注意:这是一个大对象——~200 字节,所以它不仅仅是一个周围有额外的参考计数器)。
换句话说,如果我运行:
std::list<MyObj> X;
X.resize( 1000, MyObj());
我的应用程序需要的内存是我运行时的一半:
std::list<std::unique_ptr<MyObj>> X;
for ( int i=0; i<1000; i++ ) X.push_back(std::unique_ptr<MyObj>(new MyObj()));
我已经检查了 MSFT 的实现,但没有发现任何明显的东西——有人遇到过这种情况并有什么想法吗?
编辑:好的,更清楚/具体一点。这显然是 Windows 内存使用问题,我显然遗漏了一些东西。我现在尝试了以下方法:
- 创建一个
std::listof 100000 MyObj - 创建一个
std::listof 100000 MyObj* - 创建一个 100000 int* 的
std::list - 创建一个 50000 整数的
std::list*
在每种情况下,列表的每个 add'l 成员,无论是指针还是其他,都会使我的应用程序膨胀 4400(!) 字节。这是一个 64 位版本的版本,不包含任何调试信息(链接器 > 调试 > 生成调试信息设置为否)。
我显然需要对此进行更多研究,以将其缩小到更小的测试用例。
对于那些感兴趣的人,我正在使用Process Explorer 确定应用程序大小。
原来这完全是堆碎片。多么可笑。每个 8 字节对象 4400 字节!我切换到预分配,问题完全消失了——我习惯了依赖每个对象分配的效率低下,但这太荒谬了。
MyObj 实现如下:
class MyObj
{
public:
MyObj() { memset(this,0,sizeof(MyObj)); }
double m_1;
double m_2;
double m_3;
double m_4;
double m_5;
double m_6;
double m_7;
double m_8;
double m_9;
double m_10;
double m_11;
double m_12;
double m_13;
double m_14;
double m_15;
double m_16;
double m_17;
double m_18;
double m_19;
double m_20;
double m_21;
double m_22;
double m_23;
CUnit* m_UnitPtr;
CUnitPos* m_UnitPosPtr;
};
【问题讨论】:
-
您是否看到使用原始
MyObj*的内存使用情况相同? -
您的意思是,如果我使用 new 将 1000 个 MyObjs 添加到 std::list 中?我看到与普通列表情况相同的用法,而不是 std::unique_ptr 情况。
-
试试MSVC11,他们优化了不少数据结构。此外,
unique_ptr没有引用计数器。请问MyObj的定义也能发一下吗? -
您认为用一个简短的自包含程序来演示这种行为是否可行,以便其他人可以进行试验?
-
另外,我想知道您是如何确定这一事实的。
标签: c++ unique-ptr