C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 插入地图时的内存分配大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <String>
#include <iostream>
#include <map>
#include <utility>
#include <algorithm>

void * GetMemory(size_t n) {
  void *ptr = malloc(n);
  printf("getMem n %d   ptr 0x%x\n",n,reinterpret_cast<unsigned int> (ptr));
  return ptr;
}

void FreeMemory(void *p) {
  free(p);
}

void* operator new (size_t n) {
  void *p = GetMemory(n);
  return p;
}

void* operator new [] (size_t n) {
  void *p = GetMemory(n);
  return p;
}

void operator delete (void *p) {
  FreeMemory(p);
}

void operator delete [] (void *p) {
  FreeMemory(p);
}

typedef std::vector<int> vec;

int main(int argc,char *argv[]) {
  std::map<int,vec> z;
  vec x;
  z.insert(std::pair<int,vec>(1,X));
}

编译
g -Wall -ansi test.cpp -o test

运行测试.

为什么有三次调用GetMemory n = 0?

解决方法

在FreeMemory中添加一些跟踪并将main更改为:
int main(int argc,char *argv[]) {
  printf("map\n");
  std::map<int,vec> z;
  printf("vec\n");
  vec x;
  printf("pair\n");
  std::pair<int,vec> y(1,X);
  printf("insert\n");
  z.insert(y);
  printf("inserted 1\n");
  y.first = 2;
  printf("insert\n");
  z.insert(y);
  printf("inserted 2\n");

}

输出

$make mapinsert CXXFLAGS=-O3 -B && ./mapinsert
g++ -O3    mapinsert.cpp   -o mapinsert
map
vec
pair
getMem n 0   ptr 0x6b0258
insert
getMem n 0   ptr 0x6b0268
getMem n 32   ptr 0x6b0278
getMem n 0   ptr 0x6b02a0
FreeMemory ptr 0x6b0268
inserted 1
insert
getMem n 0   ptr 0x6b0268
getMem n 32   ptr 0x6b02b0
getMem n 0   ptr 0x6b02d8
FreeMemory ptr 0x6b0268
inserted 2
FreeMemory ptr 0x6b0258
FreeMemory ptr 0x6b02d8
FreeMemory ptr 0x6b02b0
FreeMemory ptr 0x6b02a0
FreeMemory ptr 0x6b0278

你的3 0大小的分配:

>一种是将空矢量复制到对中.
>一种是在地图中存储空矢量的副本.

这两个显然是必要的.我不确定的是这个:

>一种是在插入调用中的某处复制向量,这也在插入调用中被释放.

就好像insert(或其内部调用的东西)通过值而不是通过引用获取其参数,或者insert在分配新映射节点之前的某个时间显式地将副本带入自动变量.现在解雇调试器是我的努力,我会留给别人.

编辑:神秘解决了. insert采用std :: pair< const int,vec>,而不是std :: pair< int,vec>.空向量的额外副本是因为您构造的对必须转换为(nother)临时对象,然后将对该临时对象的引用传递给insert. std :: pair有@L_696_11@构造函数模板,可以让你几乎逃脱任何事情. 20.2.2 / 4:

template<class U,class V> pair(const pair<U,V> &p);

我也观察到,在我的实现中,vec x;不调用getMem,而是调用x(0);确实.实际上:

z[1] = vec();

更少的代码并拒绝您制作额外副本的机会(尽管它调用operator =).至少对我来说,它仍然会进行2 0大小的分配.

C标准定义operator []以返回涉及对insert的调用的指定表达式的结果.我不确定这是否意味着operator []的效果“好像”make_pair和insert被调用(也就是说,标准与指定operator []必须是什么一样好,或者只是返回的值与指定表达式将产生的值相同.如果后者那么也许@L_696_11@实现可以用@L_696_11@0大小的分配来做.但是,如果没有首先创建包含映射类型的对,map肯定无法保证创建条目,因此应该预期2个分配.或者更确切地说,是所需映射值的2个副本:复制0大小的向量进行0大小分配这一事实取决于实现.

所以,如果你有@L_696_11@案例,其中复制的价值非常昂贵,但是对于认构造来说真的很便宜(比如有很多元素的容器),那么以下内容可能会有用:

std::map<int,vec> z;
vec x(1000);
z[1] = x;
// i.e. (*(z.insert(std::pair<const int,vec())).first)).second = x;

制作2个大小为4000的分配和大小为0的2,而:

std::map<int,vec> z;
vec x(1000);
z.insert(std::pair<const int,vec>(2,X));

使得3的大小为4000而没有大小为0.最终,大小足够大,以至于第@L_696_11@代码中的额外分配比第二个代码中的额外复制便宜.

我不确定C 0x中的move-constructors可能对此有所帮助.

大佬总结

以上是大佬教程为你收集整理的c – 插入地图时的内存分配全部内容,希望文章能够帮你解决c – 插入地图时的内存分配所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。