sizeof 定义在<cstddef> header,主要使用方式可以是
1. sizeof type_name
2. sizeof object
3. sizeof (object) 其中2,3情况是一样的。
如果sizeof object的object是一个引用的化,得到的结果将是整个对象的大小,比如
int a[14];sizeof a = 14*4 = 56,如果object是其他情况,那么就仅仅是指当前对象的大小,注意,对象也包括指针,一般指针大小都是4。
这些都是非常普通的问题,这里我们讨论以下两点:
string str1;
string str2("yangshiquan");
string str3("chongqing");
cout << sizeof(string) << ‘\n’ << sizeof(str1) << ‘\n’ << sizeof(str2) << ‘\n’
<< sizeof(str3) << ‘\n’
结果将输出
16
16
16
16
刚看到结果时候我非常惊讶,细细一想。string是类,sizeof统计的不再是简单的内存计算,而是string类中的所有变量所需要分配内存的大小。sizeof(string)中的string本身也是call default constructor,所以四个一样不足为奇,但是为什么是16呢?
string source code中
typedef basic_string<char, char_traits<char>, allocator<char> > string;
继续追踪:
template<class _E,
class _Tr = char_traits<_E>,
class _A = allocator<_E> >
class basic_string {…}
该模板类中如下定义了变量:
static const size_type npos;
_A allocator;
_E *_Ptr;
size_type _Len, _Res;
5?!那么大小应该是20才对,为什么是16呢?ok,static变量是不能算作对象变量的,所以pos为所有string对象维持了一个变量,也就是说,pos不为任何类对象所有,当然,在计算类所分配的空间大小的时候,pos的内存分配不计算在内,所以结果是16。npos是用于重新赋值assign的。
auto_ptr只能用于单个对象指针,但是不能用于数组,所有很多时候这个用起来并不方便,而且微软的auto_ptr并未实现reset方法,也就是在定义的时候就必须赋值。
我们感兴趣的是当两个auto_ptr指向同一个对象的时候,谁负责释放?这里采用了一个很有技巧性的方法,就是所有权,比如
auto_ptr<int> t(new int(2));t拥有该int对象的所有权,t负责释放他。
接下来我们使用t,编译器会自动在不需要t的时候free memory。
如果我们这样了,auto_ptr<int> t1 = t;显然,t和t1不能同时去free同一个对象,那么在auto_ptr底层实现的时候,t所指对象的所有权从t移到了t1,所以现在t1将负责free这个对象,而t则不再过问。这个实现非常巧妙。
另外,在指针赋值的时候,如果你写t1(t.get());那么程序就会出现不可知的问题,因为get函数简单返回底层真正的指针,而没有交出指针的所有权,
_Ty *get() const _THROW0()
{return (_Ptr); }
这时候t和t1就同时拥有了对象的所有权,你想象看,两个人拥有同一个老婆是什么后果?
所以如果想实现指针赋值,那么需要使用
t1(t.release());
_Ty *release() const _THROW0()
{((auto_ptr<_Ty> *)this)->_Owns = false;
return (_Ptr); }
我们可以看到release释放了t对该对象的所有权,所有所有权已经发生转移到t1,不会出现问题。
这里使用所有权的方式和我以前坚持的一个原则似乎有点类似。那就是,任何函数绝对不释放不是自己范围内定义的指针,不管中途你如何使用了指针,甚至给该指针重新分配空间。这点对于动态数组还是有用的,因为auto_ptr并不能管理数组内存。
另外一个让人高兴的是,auto_ptr,并不会降低程序的效率,因为本质上auto_ptr并未执行类似GC(garbage collection)的检查,只是做了本来该有你自己必须做的工作。比如
class T
{
public:
T():count(NULL) {
arr = new int[10];
for (register i = 0; i < 10; i++ )
{
arr[i] = 0;
}
}
~T(){
delete [] arr;
}
enum te{abl};
static int g;
protected:
size_t t;
private:
int *count;
int *arr;
};
auto_ptr<T> p1(new T());
p1只是简单的调用T的destructor函数,也就是说如果类的destructor函数没有显示释放你自己释放的内存,那么auto_ptr也无能为力。很多时候,auto_ptr并没有显著的作用,所有还是需要自己管理内存
-
近期文章
近期评论
bin发表在《春天来了,给笔记本洗洗澡》 A发表在《一个字,慢;两个字,很慢》 轶凡发表在《一个字,慢;两个字,很慢》 Shiquan发表在《很多格言,只要我们遵守了其中的20%就可以生活的很美好,可是…》 温世英发表在《testing should be move with…》 归档
- 2011年3月
- 2011年2月
- 2010年5月
- 2010年4月
- 2009年11月
- 2009年8月
- 2009年7月
- 2009年5月
- 2009年4月
- 2009年3月
- 2009年2月
- 2009年1月
- 2008年12月
- 2008年11月
- 2008年10月
- 2008年9月
- 2008年8月
- 2008年7月
- 2008年6月
- 2008年5月
- 2008年4月
- 2008年3月
- 2008年2月
- 2008年1月
- 2007年12月
- 2007年11月
- 2007年10月
- 2007年9月
- 2007年8月
- 2007年7月
- 2007年6月
- 2007年5月
- 2007年4月
- 2007年3月
- 2007年1月
- 2006年12月
- 2006年11月
- 2006年10月
- 2006年9月
- 2006年8月
- 2006年7月
- 2006年6月
- 2006年4月
- 2006年2月
- 2006年1月
分类
功能