[300] 散分,顺便问一题

时间:2021-12-21 03:26:18
先说明,纯灌水没分:-)

问题如下:

std::auto_ptr是标准库里的智能指针,一般用法大致如下:
...
std::auto_ptr<int> pInt( new int );
*pInt = 10;
...

偶现在的问题是这样是否合理:
...
std::auto_ptr<int> pInt( (int*)malloc(sizeof(int)) );
*pInt = 10;
...

也就是说它能否管理malloc申请的内存?
如果不能,标准库里有没有针对malloc的智能指针?
如果能,auto_ptr是如何分辨出是new分配还是malloc分配的?

60 个解决方案

#1


sf至手了!

#2


auto_ptr是调用delete删除保存的

#3


贴一段auto_ptr的实现代码

template<class _Ty>
class auto_ptr
{
~auto_ptr()
{ // destroy the object
delete _Myptr;
}
private:
_Ty *_Myptr; // the wrapped object pointer
};

#4


The template class describes an object that stores a pointer to an allocated object myptr of type Type *.  The stored pointer must either be null or designate an object allocated by a new expression. An object constructed with a nonnull pointer owns the pointer. It transfers ownership if its stored value is assigned to another object. (It replaces the stored value after a transfer with a null pointer.) The destructor for auto_ptr<Type> deletes the allocated object if it owns it. Hence, an object of class auto_ptr<Type> ensures that an allocated object is automatically deleted when control leaves a block, even through a thrown exception. You should not construct two auto_ptr<Type> objects that own the same object.

You can pass an auto_ptr<Type> object by value as an argument to a function call. You can return such an object by value as well. Both operations depend on the implicit construction of intermediate objects of class auto_ptr<Type>::auto_ptr_ref<Other>, by various subtle conversion rules. You cannot, however, reliably manage a sequence of auto_ptr<Type> objects with a Standard Template Library container.

#5


接分

#6


auto_ptr是调用delete删除保存的
那你也要改他的析构函数

#7


嗯,谢谢akirya。
这么说来auto_ptr只是简单地使用delete来管理,如果想要管理malloc申请的内存只能自己写一个了(不知道有没有)
没想到akirya一个人全占了,晕~~

akirya至少得150分,其它的分就再问一个问题,大家说说自己的编程风格吧:-)
1. 自定义类里私有变量定义写在方法前面还是后面?
2. 类的构造/析构函数写在最后还是最前还是随便放?
3. switch(...){case:... }的排版
4. 等等

注意,不能灌水(不然老妖要把我的帖子丢水区去的:-P)

#8


1 使用频率高的在前面,不高的在后面。
2 cpp文件的最前
3 俺是紧凑风格的除了函数实现的{单独一行外其他的都不是独立一样的。
其他的是能用stl就用stl。写函数不超过50行,const 匿名空间 遍地都是。

#9


该回复于2008-07-04 22:16:32被版主删除

#10


混点毛毛的分

:-)
1.放前面
2.通常是最前面,简单就加inline
3.

switch(i)
{
 case 0:........break;
 case 1:........break;
 default:...break;

}


4.等啥呀/? 嘿嘿

#11


1.前面
2.include文件的下面 这样找起来也比较方便。
3.
switch(i)
{
   case 0:
        ...........;
        break;  
   case 1:
        ...........;
        break;
   case 2:
        ...........;
        break;
   default:
        ..........;
        break;
}

#12


学习中

#13


1.前面
2.前面
3.我用CB写代码都不注意排版,写完了放在VC里面用它的自动排版功能...

#14


现在有插件可以排版拉

#15


该回复于2008-07-05 13:59:06被版主删除

#16


学习

#17


不懂,向楼主学习。

#18


毛毛 去看看auto_ptr的源代码便知

另外最好研读一下 boost里面智能指针的管理 使用带计数功能的方式进行安全释放 我想或许更适合你
更具体的毛毛自己应该可以搞定 方法就是上面的

#19


信仰兄:说了是散分嘛:-)
散水分觉得没意思。正好遇到公司一位仁兄的代码里有用auto_ptr管理malloc内存的(可能他是auto_ptr的funs,整个程序全是这个东西)。因为没出啥错,偶也一直没在意,前几天突然觉得有点刺眼就多看了两眼。 (不过现在发现用这个问题不适合散分,被akirya一人全抢了,偶只好厚着脸皮从他那里抢回150分的“个人所得税”再分配了-_-)

boost里的指针是不错,种类丰富,而且可扩展,偶就等它进标准库了,呵呵(loki里基于策略的指针也不错,值得一看,不过用在项目里就...)

#20


不会 帮顶 不要分

#21


1 虽然这样,malloc申请的空间受到限制
2 释放的时候用什么来处理了

#22


不太懂,学习了

#23


:-) 分多给他点 他可以升星 我不要了
只是本着讨论的方式过来的

loki大致看过一点,并没有在实际的项目中用过
而boost里面的有几个非常不错,主要是里面的实现思想非常不错
所以推荐给你

另外对于auto_ptr并不是万能的 要注意在很多时候的安全问题
比如放入 容器中的时候要千万注意 可能生命周期结束后就被释放了 会导致很严重的非法指针情况
所以从安全的考虑 基于计数器的智能指针可能更加适合在容器中存储使用

当然对于简单的应用auto_ptr已经足够了

至于你提到的boost标准化 估计还需要一些历程 看看委员会他们的思路了
C++0x现在感觉反而没落了,或许是自己很久不去了解了 反而慢慢成了微软那泡慢慢升温的泉水中的青蛙
有点无法自拔

昨天我的N95到货了 可能以后会做Symbian的开发工作 当然还好也是基于C++的
bless

更多的讨论 欢迎去我的个人博客
http://www.server-development.cn

#24


不太懂,学习了

#25


loki的方法扩展性非常好,只是偶觉得因为它的技巧性太强而不适合项目里使用。
其实boost里的很多东东也有这个问题,貌似提供了方便的东东,但它的实现实在是太“BT”了,如果用在项目中就得要求Term里所有成员对C++有相当的理解。(以上都是个人观点:-P)

回到正题,继续讨论代码风格:-)

#26


等接升星,前来接分。。。。。。。。。。

#27


有一个好的讨论问题不容易,置顶了。欢迎大家讨论。

#28


引用 5 楼 loveshell 的回复:
接分

#29


1. 自定义类里私有变量定义写在方法后面,而且是类定义的最后.
2. 类的构造/析构函数写在最前.
3. switch(...)
   {
    case:
       ...;
       break;
    case:
       ...;
       break;
    default:
       ....;
       break;
   }

#30



/*
 * Copyright (c) 1997-1999
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted 
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
 */

#ifndef _STLP_AUTO_PTR_H
# define _STLP_AUTO_PTR_H

_STLP_BEGIN_NAMESPACE
// implementation primitive
class __ptr_base {
public:
  void* _M_p;
  void  __set(const void* __p) { _M_p = __CONST_CAST(void*,__p); }
  void  __set(void* __p) { _M_p = __p; }
};

template <class _Tp> class auto_ptr_ref {
public:
  __ptr_base& _M_r;
  _Tp* const _M_p;

  auto_ptr_ref(__ptr_base& __r, _Tp* __p) : _M_r(__r), _M_p(__p) {  }

  _Tp* release() const { _M_r.__set((void*)0); return _M_p; }

};

template<class _Tp> struct auto_ptr :  public __ptr_base {

  typedef _Tp element_type;
  typedef auto_ptr<_Tp>           _Self;
  
  _Tp* release() {  
    _Tp* __px = this->get(); 
    this->_M_p = 0; 
    return __px; 
  }
  
  void reset(_Tp* __px=0) {
    _Tp* __pt = this->get();
    if (__px != __pt) 
      delete __pt; 
    this->__set(__px); 
  }

  _Tp* get() const { return __REINTERPRET_CAST(_Tp*,__CONST_CAST(void*,_M_p)); } 

# if !defined (_STLP_NO_ARROW_OPERATOR)
  _Tp* operator->() const { return get(); }
# endif
  _Tp& operator*() const  { return *get(); }
  
  auto_ptr() { this->_M_p = 0; }
  
  explicit auto_ptr(_Tp* __px) { this->__set(__px); }
  
#if defined (_STLP_MEMBER_TEMPLATES)
# if OBSOLETE // def _STLP_MSVC
  template<class _Tp1> auto_ptr(const auto_ptr<_Tp1>& __r) {
    this->__set((_Tp1*)const_cast<auto_ptr<_Tp1> >(__r).release());
  }
  template<class _Tp1> auto_ptr<_Tp>& operator=(const auto_ptr<_Tp1>& __r) {
    reset((_Tp1*)const_cast<auto_ptr<_Tp1> >(__r).release());
    return *this;
  }
# else
# if !defined (_STLP_NO_TEMPLATE_CONVERSIONS)
  template<class _Tp1> auto_ptr(auto_ptr<_Tp1>& __r) {
    this->__set((_Tp1*)__r.release());
  }
# endif
  template<class _Tp1> auto_ptr<_Tp>& operator=(auto_ptr<_Tp1>& __r) {
    reset((_Tp1*)__r.release());
    return *this;
  }
# endif
#endif /* _STLP_MEMBER_TEMPLATES */
  
#ifdef OBSOLETE // def _STLP_MSVC
  auto_ptr(const _Self& __r) { this->__set(const_cast<_Self&>(__r).release()); }
  
  _Self& operator=(const _Self& __r)  {
    reset(const_cast<_Self&>(__r).release());
    return *this;
  }
#else
  auto_ptr(_Self& __r) { this->__set(__r.release()); }

  _Self& operator=(_Self& __r)  {
    reset(__r.release());
    return *this;
  }
#endif

  ~auto_ptr() { /* boris : reset(0) might be better */ delete this->get(); }

  auto_ptr(auto_ptr_ref<_Tp> __r) {
    this->__set(__r.release());
  }

  _Self& operator=(auto_ptr_ref<_Tp> __r) {
    reset(__r.release());
    return *this;
  }
  
# if defined(_STLP_MEMBER_TEMPLATES) && !defined(_STLP_NO_TEMPLATE_CONVERSIONS)
  template<class _Tp1> operator auto_ptr_ref<_Tp1>() {
    return auto_ptr_ref<_Tp1>(*this, this->get());
  }
  template<class _Tp1> operator auto_ptr<_Tp1>() {
    return auto_ptr<_Tp1>(release());
  }
# else
  operator auto_ptr_ref<_Tp>()
  { return auto_ptr_ref<_Tp>(*this, this->get()); }
# endif

};
_STLP_END_NAMESPACE

#endif /* _STLP_AUTO_PTR_H */

// Local Variables:
// mode:C++
// End:




这是auto_ptr的代码
先贴出来 再大家来一起分析一下 毛毛的时候可以

#31


没有注意到 原来大家换问题了:

>>1. 自定义类里私有变量定义写在方法前面还是后面? 
这个看个人的喜好了,放在前面给人感觉一看就是知道该类的数据结构思想
BS的C++Programming 讨论过这个问题 我觉得其实无妨大雅
>>2. 类的构造/析构函数写在最后还是最前还是随便放? 
这个一般是在最前面 起码我是这么做的 偶尔出现多个重载构造函数的时候 可能会顺序换换
>>3. switch(...){case:... }的排版 
很多时候并不喜欢这样子 我更欣赏的是通过其他模式来转化这样的
甚至直接用if/elseif/else了

>>等等

#32


malloc分配的内存,可以用delete来释放

#33


引用 11 楼 shanxmxj 的回复:
1.前面 
2.include文件的下面 这样找起来也比较方便。 
3. 
switch(i) 

  case 0: 
        ...........; 
        break;  
  case 1: 
        ...........; 
        break; 
  case 2: 
        ...........; 
        break; 
  default: 
        ..........; 
        break; 
}



好像只会回答这个问题...和这个一样.

#34


看不懂

#35


该回复于2008-07-08 08:49:24被版主删除

#36


引用 32 楼 xpdavis 的回复:
malloc分配的内存,可以用delete来释放

说起来应该是这样(delete看起来象是free + 析构),不过几乎所有的书上都表示不要这么做,BCB里的CodeGuard也反对-_- 
不过用起来貌似还真没啥问题,偶的汇编能力太差,不敢肯定这样是不是能真正删除。看楼下的了。

to信仰:偶是怕散分不均匀所以加了个普遍又没固定答案的问题:-),随便啦,偶更想在这里讨论智能指针的问题,包括标准库的auto_ptr, boost里的scoped_ptr,shared_ptr,weak_ptr, loki里的SmartPtr等等。大家也可以分享一下好用的自定义的智能指针啊:-)

另外,妖哥置顶的时候把auto_ptr写成了auto_prt

#37


malloc分配的内存,可以用delete来释放,不要這樣做。

就算測試過,行,也不要這樣做。 malloc free 是C庫用來分配釋放內存的,new 與 delet 則屬於 C++ 的內容。只是C++要兼容C才保留了下來。malloc free 體系 與  new delete 體系可能分別屬於不同的內存管理器或采用不同的管理策略,當然也可能使用同一內存管理器,這要看具體的編譯器怎麼做的了。混用,可能正常,也可能不正常,也就是結果不可預測。或許在這個版本是對的,但換個編譯器或換個版本就可能出錯的代碼還是要不得的。

   在C++中,建議出現 malloc 的地方,就算違規,非要使用的話就封裝在特定的單元中,一般是為了那個隨時可能調用失敗的 ralloc 來擴張內存以提高點點執行效率。

#38


恩,昨天没细看,果然是写错了。笔误。

#39


学习,接分

#40


>>1. 自定义类里私有变量定义写在方法前面还是后面? 
我習慣將變量寫在一起,可以清楚知道數據結構。復雜的類中,public或是 protected等可以多處寫的嘛。

>>2. 类的构造/析构函数写在最后还是最前还是随便放? 
實現代碼放在一起,聲明也是放在一起,不管是最前或最後,一般我放前面。

>>3. switch(...){case:... }的排版 
  不同的代碼可能其組織方式不一樣。

不贊成將代碼排版方式條文化,希望能在排版中更好地表現出段落的含義。

如:int a,b,c,d,e,f,g ; //就沒必要一定分開每行只聲明一個。因為分開後占用行數過多,一個函數行數過多,會讓人不舒服;一個足夠內聚的函數非要分開成多個函數,也同樣令人不舒服。排版就是兼顧規范,行數,段落意義,美觀易讀及行業習慣而得出的。 不要將編碼規范視為神聖不可侵犯的。說些例子:
排版1:等號對齊
sin.abc   = a.abc ;
sin.acdfe = a.acdfe ; 
sin.a     = a.a ; 
排版2:
sin.abc = a.abc ;
sin.acdfe = a.acdfe ; 
sin.a = a.a ; 

多行時,明顯,等號對齊的排版美觀易讀,可以一目十行,一下子看完整個段落。而排版2就需要慢慢看了。
但只有兩三行時,采用等號對齊就沒這樣的效果。

switch(a)
{
  case 0 : //注釋
            x= a ; 
          break ; 
  case ..... 
}
有注釋時,放在case 後,可以很清楚地知道 變量的意義。
switch(a)
{
  case 0 : x  = a ; break ; 
  case 1 : y  = a ; break ; 
  case 2 : z  = a ; break ; 
  case 3 : xx = a ; break ; 
  case 4 : yy = a ; break ; 

  default: zz = a ; break ;  //空一行可以突出默認值。也可以不空,因為一般在IDE中default是突出顯示的。 
}
這樣的編排則可以減少行數,而其意義也明確表示,比分行更易讀,因為可以一下子看完整個段落。

不是說不用遵守規范,一般情況下按規范書寫,部分段落*掌握。書寫的原則是讓讀代碼的人更易讀,版面更美觀。

C/C++是*自在的,但不是隨隨便便邋邋遢遢的,我是不贊成將代碼格式公式化的人。

#41


PPower说的有道理,反正偶是不敢这么用。

在妖哥置顶的激励下,不得不弄点小成绩出来,呵呵:-)

用auto_ptr管理malloc分配的指针
不会?!!!有没有办法???

用boost的shared_ptr来管理malloc分配的指针
{
    boost::shared_ptr<int> pInt((int*)malloc(sizeof(int)), &free);
    *pInt = 10;
}

用loki的SmartPtr来管理malloc分配的指针
template<class T>
struct FreeStorage :  // 偶想找找Loki有没有自带free策略,结果没找到,只好新建一个free的删除策略了
    public Loki::DefaultSPStorage<T>
{
    typedef typename Loki::DefaultSPStorage<T>::StoredType StoredType;
    typedef typename Loki::DefaultSPStorage<T>::PointerType PointerType;
    typedef typename Loki::DefaultSPStorage<T>::ReferenceType ReferenceType;

    FreeStorage(const StoredType& p)
        : Loki::DefaultSPStorage<T>(p) {}

    void Destroy()
    { free(GetImplRef(*this)); }   // 使用free
};

使用Loki::SmartPtr
{
    Loki::SmartPtr<int,             // int类型
        Loki::RefCounted,           // 引用计数策略
        Loki::DisallowConversion,   // 不允许隐式转换成T*
        Loki::NoCheck,              // 使用中不检查空指针
        FreeStorage                 // 我们定义的free存储策略
> pInt((int*)malloc(sizeof(int)));
    *pInt = 10;
}

#42


学习了

#43


其实使用auto_ptr的原因,就是为了把指针变是局部变量,这样在auto_ptr退出其作用域的时候,会自动释放其指向的指针。这样做的最终目标,就是避免可能的内存泄漏的问题。如果,你有良好指针使用原则和习惯,就完全没有必要使用auto_ptr,我就从来不用它。对于我而言,使用指针是为了提高效率,使用auto_ptr,只是画蛇添足。

#44


new比malloc多了构造
delete比free多了析构
如此而已
不推荐不代表使用了会有问题

#45


不懂,学习中

#46


...

#47


偶是来做俯卧撑的!楼下继续!

#48


malloc和new的内存分配机制实际上是一样的,
至少在WINDOWS中是这样,混用应该没有什么问题.

#49


1. 自定义类里私有变量定义写在方法前面还是后面? 
   习惯写在前面,也许是养成了C语言的那种习惯吧。觉得这亲数据和操作分开更舒服。
2. 类的构造/析构函数写在最后还是最前还是随便放? 
    习惯将它们放在方法的最前面。这样容易定位。
3. switch(...){case:... }的排版 
    采用VS的那种自动缩进,觉得很不错。
4. 注释:在编程方面前面加些注释进行说明,在成员变量中也要加些注释,有些还注册使用方法及意义等,不然呀,久了就忘了。

#50


引用 43 楼 zdhsoft 的回复:
其实使用auto_ptr的原因,就是为了把指针变是局部变量,这样在auto_ptr退出其作用域的时候,会自动释放其指向的指针。这样做的最终目标,就是避免可能的内存泄漏的问题。如果,你有良好指针使用原则和习惯,就完全没有必要使用auto_ptr,我就从来不用它。对于我而言,使用指针是为了提高效率,使用auto_ptr,只是画蛇添足。


要是有异常呢? 一个函数有多个退出点呢?

#1


sf至手了!

#2


auto_ptr是调用delete删除保存的

#3


贴一段auto_ptr的实现代码

template<class _Ty>
class auto_ptr
{
~auto_ptr()
{ // destroy the object
delete _Myptr;
}
private:
_Ty *_Myptr; // the wrapped object pointer
};

#4


The template class describes an object that stores a pointer to an allocated object myptr of type Type *.  The stored pointer must either be null or designate an object allocated by a new expression. An object constructed with a nonnull pointer owns the pointer. It transfers ownership if its stored value is assigned to another object. (It replaces the stored value after a transfer with a null pointer.) The destructor for auto_ptr<Type> deletes the allocated object if it owns it. Hence, an object of class auto_ptr<Type> ensures that an allocated object is automatically deleted when control leaves a block, even through a thrown exception. You should not construct two auto_ptr<Type> objects that own the same object.

You can pass an auto_ptr<Type> object by value as an argument to a function call. You can return such an object by value as well. Both operations depend on the implicit construction of intermediate objects of class auto_ptr<Type>::auto_ptr_ref<Other>, by various subtle conversion rules. You cannot, however, reliably manage a sequence of auto_ptr<Type> objects with a Standard Template Library container.

#5


接分

#6


auto_ptr是调用delete删除保存的
那你也要改他的析构函数

#7


嗯,谢谢akirya。
这么说来auto_ptr只是简单地使用delete来管理,如果想要管理malloc申请的内存只能自己写一个了(不知道有没有)
没想到akirya一个人全占了,晕~~

akirya至少得150分,其它的分就再问一个问题,大家说说自己的编程风格吧:-)
1. 自定义类里私有变量定义写在方法前面还是后面?
2. 类的构造/析构函数写在最后还是最前还是随便放?
3. switch(...){case:... }的排版
4. 等等

注意,不能灌水(不然老妖要把我的帖子丢水区去的:-P)

#8


1 使用频率高的在前面,不高的在后面。
2 cpp文件的最前
3 俺是紧凑风格的除了函数实现的{单独一行外其他的都不是独立一样的。
其他的是能用stl就用stl。写函数不超过50行,const 匿名空间 遍地都是。

#9


该回复于2008-07-04 22:16:32被版主删除

#10


混点毛毛的分

:-)
1.放前面
2.通常是最前面,简单就加inline
3.

switch(i)
{
 case 0:........break;
 case 1:........break;
 default:...break;

}


4.等啥呀/? 嘿嘿

#11


1.前面
2.include文件的下面 这样找起来也比较方便。
3.
switch(i)
{
   case 0:
        ...........;
        break;  
   case 1:
        ...........;
        break;
   case 2:
        ...........;
        break;
   default:
        ..........;
        break;
}

#12


学习中

#13


1.前面
2.前面
3.我用CB写代码都不注意排版,写完了放在VC里面用它的自动排版功能...

#14


现在有插件可以排版拉

#15


该回复于2008-07-05 13:59:06被版主删除

#16


学习

#17


不懂,向楼主学习。

#18


毛毛 去看看auto_ptr的源代码便知

另外最好研读一下 boost里面智能指针的管理 使用带计数功能的方式进行安全释放 我想或许更适合你
更具体的毛毛自己应该可以搞定 方法就是上面的

#19


信仰兄:说了是散分嘛:-)
散水分觉得没意思。正好遇到公司一位仁兄的代码里有用auto_ptr管理malloc内存的(可能他是auto_ptr的funs,整个程序全是这个东西)。因为没出啥错,偶也一直没在意,前几天突然觉得有点刺眼就多看了两眼。 (不过现在发现用这个问题不适合散分,被akirya一人全抢了,偶只好厚着脸皮从他那里抢回150分的“个人所得税”再分配了-_-)

boost里的指针是不错,种类丰富,而且可扩展,偶就等它进标准库了,呵呵(loki里基于策略的指针也不错,值得一看,不过用在项目里就...)

#20


不会 帮顶 不要分

#21


1 虽然这样,malloc申请的空间受到限制
2 释放的时候用什么来处理了

#22


不太懂,学习了

#23


:-) 分多给他点 他可以升星 我不要了
只是本着讨论的方式过来的

loki大致看过一点,并没有在实际的项目中用过
而boost里面的有几个非常不错,主要是里面的实现思想非常不错
所以推荐给你

另外对于auto_ptr并不是万能的 要注意在很多时候的安全问题
比如放入 容器中的时候要千万注意 可能生命周期结束后就被释放了 会导致很严重的非法指针情况
所以从安全的考虑 基于计数器的智能指针可能更加适合在容器中存储使用

当然对于简单的应用auto_ptr已经足够了

至于你提到的boost标准化 估计还需要一些历程 看看委员会他们的思路了
C++0x现在感觉反而没落了,或许是自己很久不去了解了 反而慢慢成了微软那泡慢慢升温的泉水中的青蛙
有点无法自拔

昨天我的N95到货了 可能以后会做Symbian的开发工作 当然还好也是基于C++的
bless

更多的讨论 欢迎去我的个人博客
http://www.server-development.cn

#24


不太懂,学习了

#25


loki的方法扩展性非常好,只是偶觉得因为它的技巧性太强而不适合项目里使用。
其实boost里的很多东东也有这个问题,貌似提供了方便的东东,但它的实现实在是太“BT”了,如果用在项目中就得要求Term里所有成员对C++有相当的理解。(以上都是个人观点:-P)

回到正题,继续讨论代码风格:-)

#26


等接升星,前来接分。。。。。。。。。。

#27


有一个好的讨论问题不容易,置顶了。欢迎大家讨论。

#28


引用 5 楼 loveshell 的回复:
接分

#29


1. 自定义类里私有变量定义写在方法后面,而且是类定义的最后.
2. 类的构造/析构函数写在最前.
3. switch(...)
   {
    case:
       ...;
       break;
    case:
       ...;
       break;
    default:
       ....;
       break;
   }

#30



/*
 * Copyright (c) 1997-1999
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted 
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
 */

#ifndef _STLP_AUTO_PTR_H
# define _STLP_AUTO_PTR_H

_STLP_BEGIN_NAMESPACE
// implementation primitive
class __ptr_base {
public:
  void* _M_p;
  void  __set(const void* __p) { _M_p = __CONST_CAST(void*,__p); }
  void  __set(void* __p) { _M_p = __p; }
};

template <class _Tp> class auto_ptr_ref {
public:
  __ptr_base& _M_r;
  _Tp* const _M_p;

  auto_ptr_ref(__ptr_base& __r, _Tp* __p) : _M_r(__r), _M_p(__p) {  }

  _Tp* release() const { _M_r.__set((void*)0); return _M_p; }

};

template<class _Tp> struct auto_ptr :  public __ptr_base {

  typedef _Tp element_type;
  typedef auto_ptr<_Tp>           _Self;
  
  _Tp* release() {  
    _Tp* __px = this->get(); 
    this->_M_p = 0; 
    return __px; 
  }
  
  void reset(_Tp* __px=0) {
    _Tp* __pt = this->get();
    if (__px != __pt) 
      delete __pt; 
    this->__set(__px); 
  }

  _Tp* get() const { return __REINTERPRET_CAST(_Tp*,__CONST_CAST(void*,_M_p)); } 

# if !defined (_STLP_NO_ARROW_OPERATOR)
  _Tp* operator->() const { return get(); }
# endif
  _Tp& operator*() const  { return *get(); }
  
  auto_ptr() { this->_M_p = 0; }
  
  explicit auto_ptr(_Tp* __px) { this->__set(__px); }
  
#if defined (_STLP_MEMBER_TEMPLATES)
# if OBSOLETE // def _STLP_MSVC
  template<class _Tp1> auto_ptr(const auto_ptr<_Tp1>& __r) {
    this->__set((_Tp1*)const_cast<auto_ptr<_Tp1> >(__r).release());
  }
  template<class _Tp1> auto_ptr<_Tp>& operator=(const auto_ptr<_Tp1>& __r) {
    reset((_Tp1*)const_cast<auto_ptr<_Tp1> >(__r).release());
    return *this;
  }
# else
# if !defined (_STLP_NO_TEMPLATE_CONVERSIONS)
  template<class _Tp1> auto_ptr(auto_ptr<_Tp1>& __r) {
    this->__set((_Tp1*)__r.release());
  }
# endif
  template<class _Tp1> auto_ptr<_Tp>& operator=(auto_ptr<_Tp1>& __r) {
    reset((_Tp1*)__r.release());
    return *this;
  }
# endif
#endif /* _STLP_MEMBER_TEMPLATES */
  
#ifdef OBSOLETE // def _STLP_MSVC
  auto_ptr(const _Self& __r) { this->__set(const_cast<_Self&>(__r).release()); }
  
  _Self& operator=(const _Self& __r)  {
    reset(const_cast<_Self&>(__r).release());
    return *this;
  }
#else
  auto_ptr(_Self& __r) { this->__set(__r.release()); }

  _Self& operator=(_Self& __r)  {
    reset(__r.release());
    return *this;
  }
#endif

  ~auto_ptr() { /* boris : reset(0) might be better */ delete this->get(); }

  auto_ptr(auto_ptr_ref<_Tp> __r) {
    this->__set(__r.release());
  }

  _Self& operator=(auto_ptr_ref<_Tp> __r) {
    reset(__r.release());
    return *this;
  }
  
# if defined(_STLP_MEMBER_TEMPLATES) && !defined(_STLP_NO_TEMPLATE_CONVERSIONS)
  template<class _Tp1> operator auto_ptr_ref<_Tp1>() {
    return auto_ptr_ref<_Tp1>(*this, this->get());
  }
  template<class _Tp1> operator auto_ptr<_Tp1>() {
    return auto_ptr<_Tp1>(release());
  }
# else
  operator auto_ptr_ref<_Tp>()
  { return auto_ptr_ref<_Tp>(*this, this->get()); }
# endif

};
_STLP_END_NAMESPACE

#endif /* _STLP_AUTO_PTR_H */

// Local Variables:
// mode:C++
// End:




这是auto_ptr的代码
先贴出来 再大家来一起分析一下 毛毛的时候可以

#31


没有注意到 原来大家换问题了:

>>1. 自定义类里私有变量定义写在方法前面还是后面? 
这个看个人的喜好了,放在前面给人感觉一看就是知道该类的数据结构思想
BS的C++Programming 讨论过这个问题 我觉得其实无妨大雅
>>2. 类的构造/析构函数写在最后还是最前还是随便放? 
这个一般是在最前面 起码我是这么做的 偶尔出现多个重载构造函数的时候 可能会顺序换换
>>3. switch(...){case:... }的排版 
很多时候并不喜欢这样子 我更欣赏的是通过其他模式来转化这样的
甚至直接用if/elseif/else了

>>等等

#32


malloc分配的内存,可以用delete来释放

#33


引用 11 楼 shanxmxj 的回复:
1.前面 
2.include文件的下面 这样找起来也比较方便。 
3. 
switch(i) 

  case 0: 
        ...........; 
        break;  
  case 1: 
        ...........; 
        break; 
  case 2: 
        ...........; 
        break; 
  default: 
        ..........; 
        break; 
}



好像只会回答这个问题...和这个一样.

#34


看不懂

#35


该回复于2008-07-08 08:49:24被版主删除

#36


引用 32 楼 xpdavis 的回复:
malloc分配的内存,可以用delete来释放

说起来应该是这样(delete看起来象是free + 析构),不过几乎所有的书上都表示不要这么做,BCB里的CodeGuard也反对-_- 
不过用起来貌似还真没啥问题,偶的汇编能力太差,不敢肯定这样是不是能真正删除。看楼下的了。

to信仰:偶是怕散分不均匀所以加了个普遍又没固定答案的问题:-),随便啦,偶更想在这里讨论智能指针的问题,包括标准库的auto_ptr, boost里的scoped_ptr,shared_ptr,weak_ptr, loki里的SmartPtr等等。大家也可以分享一下好用的自定义的智能指针啊:-)

另外,妖哥置顶的时候把auto_ptr写成了auto_prt

#37


malloc分配的内存,可以用delete来释放,不要這樣做。

就算測試過,行,也不要這樣做。 malloc free 是C庫用來分配釋放內存的,new 與 delet 則屬於 C++ 的內容。只是C++要兼容C才保留了下來。malloc free 體系 與  new delete 體系可能分別屬於不同的內存管理器或采用不同的管理策略,當然也可能使用同一內存管理器,這要看具體的編譯器怎麼做的了。混用,可能正常,也可能不正常,也就是結果不可預測。或許在這個版本是對的,但換個編譯器或換個版本就可能出錯的代碼還是要不得的。

   在C++中,建議出現 malloc 的地方,就算違規,非要使用的話就封裝在特定的單元中,一般是為了那個隨時可能調用失敗的 ralloc 來擴張內存以提高點點執行效率。

#38


恩,昨天没细看,果然是写错了。笔误。

#39


学习,接分

#40


>>1. 自定义类里私有变量定义写在方法前面还是后面? 
我習慣將變量寫在一起,可以清楚知道數據結構。復雜的類中,public或是 protected等可以多處寫的嘛。

>>2. 类的构造/析构函数写在最后还是最前还是随便放? 
實現代碼放在一起,聲明也是放在一起,不管是最前或最後,一般我放前面。

>>3. switch(...){case:... }的排版 
  不同的代碼可能其組織方式不一樣。

不贊成將代碼排版方式條文化,希望能在排版中更好地表現出段落的含義。

如:int a,b,c,d,e,f,g ; //就沒必要一定分開每行只聲明一個。因為分開後占用行數過多,一個函數行數過多,會讓人不舒服;一個足夠內聚的函數非要分開成多個函數,也同樣令人不舒服。排版就是兼顧規范,行數,段落意義,美觀易讀及行業習慣而得出的。 不要將編碼規范視為神聖不可侵犯的。說些例子:
排版1:等號對齊
sin.abc   = a.abc ;
sin.acdfe = a.acdfe ; 
sin.a     = a.a ; 
排版2:
sin.abc = a.abc ;
sin.acdfe = a.acdfe ; 
sin.a = a.a ; 

多行時,明顯,等號對齊的排版美觀易讀,可以一目十行,一下子看完整個段落。而排版2就需要慢慢看了。
但只有兩三行時,采用等號對齊就沒這樣的效果。

switch(a)
{
  case 0 : //注釋
            x= a ; 
          break ; 
  case ..... 
}
有注釋時,放在case 後,可以很清楚地知道 變量的意義。
switch(a)
{
  case 0 : x  = a ; break ; 
  case 1 : y  = a ; break ; 
  case 2 : z  = a ; break ; 
  case 3 : xx = a ; break ; 
  case 4 : yy = a ; break ; 

  default: zz = a ; break ;  //空一行可以突出默認值。也可以不空,因為一般在IDE中default是突出顯示的。 
}
這樣的編排則可以減少行數,而其意義也明確表示,比分行更易讀,因為可以一下子看完整個段落。

不是說不用遵守規范,一般情況下按規范書寫,部分段落*掌握。書寫的原則是讓讀代碼的人更易讀,版面更美觀。

C/C++是*自在的,但不是隨隨便便邋邋遢遢的,我是不贊成將代碼格式公式化的人。

#41


PPower说的有道理,反正偶是不敢这么用。

在妖哥置顶的激励下,不得不弄点小成绩出来,呵呵:-)

用auto_ptr管理malloc分配的指针
不会?!!!有没有办法???

用boost的shared_ptr来管理malloc分配的指针
{
    boost::shared_ptr<int> pInt((int*)malloc(sizeof(int)), &free);
    *pInt = 10;
}

用loki的SmartPtr来管理malloc分配的指针
template<class T>
struct FreeStorage :  // 偶想找找Loki有没有自带free策略,结果没找到,只好新建一个free的删除策略了
    public Loki::DefaultSPStorage<T>
{
    typedef typename Loki::DefaultSPStorage<T>::StoredType StoredType;
    typedef typename Loki::DefaultSPStorage<T>::PointerType PointerType;
    typedef typename Loki::DefaultSPStorage<T>::ReferenceType ReferenceType;

    FreeStorage(const StoredType& p)
        : Loki::DefaultSPStorage<T>(p) {}

    void Destroy()
    { free(GetImplRef(*this)); }   // 使用free
};

使用Loki::SmartPtr
{
    Loki::SmartPtr<int,             // int类型
        Loki::RefCounted,           // 引用计数策略
        Loki::DisallowConversion,   // 不允许隐式转换成T*
        Loki::NoCheck,              // 使用中不检查空指针
        FreeStorage                 // 我们定义的free存储策略
> pInt((int*)malloc(sizeof(int)));
    *pInt = 10;
}

#42


学习了

#43


其实使用auto_ptr的原因,就是为了把指针变是局部变量,这样在auto_ptr退出其作用域的时候,会自动释放其指向的指针。这样做的最终目标,就是避免可能的内存泄漏的问题。如果,你有良好指针使用原则和习惯,就完全没有必要使用auto_ptr,我就从来不用它。对于我而言,使用指针是为了提高效率,使用auto_ptr,只是画蛇添足。

#44


new比malloc多了构造
delete比free多了析构
如此而已
不推荐不代表使用了会有问题

#45


不懂,学习中

#46


...

#47


偶是来做俯卧撑的!楼下继续!

#48


malloc和new的内存分配机制实际上是一样的,
至少在WINDOWS中是这样,混用应该没有什么问题.

#49


1. 自定义类里私有变量定义写在方法前面还是后面? 
   习惯写在前面,也许是养成了C语言的那种习惯吧。觉得这亲数据和操作分开更舒服。
2. 类的构造/析构函数写在最后还是最前还是随便放? 
    习惯将它们放在方法的最前面。这样容易定位。
3. switch(...){case:... }的排版 
    采用VS的那种自动缩进,觉得很不错。
4. 注释:在编程方面前面加些注释进行说明,在成员变量中也要加些注释,有些还注册使用方法及意义等,不然呀,久了就忘了。

#50


引用 43 楼 zdhsoft 的回复:
其实使用auto_ptr的原因,就是为了把指针变是局部变量,这样在auto_ptr退出其作用域的时候,会自动释放其指向的指针。这样做的最终目标,就是避免可能的内存泄漏的问题。如果,你有良好指针使用原则和习惯,就完全没有必要使用auto_ptr,我就从来不用它。对于我而言,使用指针是为了提高效率,使用auto_ptr,只是画蛇添足。


要是有异常呢? 一个函数有多个退出点呢?