《程序员》杂志专家门诊C/C++问题

babysloth 2002-04-19 11:17:48
下面是《程序员》杂志第5期中专家门诊部分的C/C++问题,我整理了几个,大家能否看看有没有什么问题。

由于这次时间仓促,没有及时与大家商量,非常抱歉。以后希望大家多提建议,推荐您认为好的问题,共同学习。

----------------------------------------------

需要在 p = new xxx()之后检查NULL吗?

按现行标准,如果内存分配失败,则会抛出std::bad_alloc异常。但有些编译器仍遵循以前的方式:返回0,例如Microsoft Visual C++。不过从VC7开始,CRT仍采取这样的方式,但VC中的C++标准库则支持抛出异常之一标准方式。详细情况请见MSDN。

另外,标准委员会为了与以前保持一致性,也提供了不抛出异常的方式:

xxx *p = new (nothrow) xxx;

这时就不妨用assert(p)。

相关问题在Effective C++上有非常精彩的描述,请参考。


----------------------------------------------



如何安全地将多态指针放进STL容器?

class A{};
class C: public A{};
// 以vector为例,如果
vector<A*> vec;
vec.push_back(new C());

问题出现如何对容器中的指针进行管理上,假如直接把指针放到容器里,然后在进行删除元素操作和容器的析构器中释放元素指向的内存,听起来似乎井井有条,但是如果一个容器中有多个元素指向同一个对象或者多个指向同一个对象的元素被包含到多个容器中,就会带来一片混乱


那么用标准库中的auto_ptr来管理指针又会如何呢?情况可能会更糟,不但老问题不能解决,还带来了新问题,auto_ptr只是简单地将指针的管理权在对象之间转移,假如在对容器进行操作的算法中将元素的管理权交给了临时对象,那么当算法完成后临时对象将自动地释放该元素指向的内存,结果将不堪设想。毕竟,auto_ptr是典型的“一拷就坏(Copy Destructive)”。

有一种解决办法是专门用一个容器来保存所有的动态对象,只有该容器可以删除对象,其他容器只保留指向这些对象的指针。当然这种做法比较烦。另一种简单的方法是利用Boost库(介绍见《程序员》2002年3月号的《走进Boost》一文)中的shared_ptr。

#include <list>
#include <boost/shared_ptr.hpp>
class A{};
class C: public A{};

void g()
{
typedef boost::shared_ptr<A> element_type;
typedef std::list<element_type> list_type;

list_type ll;
ll.push_back(element_type(new C));
}

这个比auto_ptr复杂得多的东东管理的是对象的引用计数,当计数为0时自动释放内存,呵呵,真是个好管家。


----------------------------------------------


一个std::string对象,要把这个对象两端多余的空格去掉,怎么办?

可以利用string的成员函数find_first_not_of和find_last_not_of:

#include <iostream>
#include <string>

template <class T> void trim(std::basic_string<T>& s)
{
const char c = ' ';
s.erase(0, s.find_first_not_of(c));
s.erase(s.find_last_not_of(c) + 1);
}

void main()
{
using namespace std;
string str(" 123 456 789 ");
trim(str);
cout << str << '$' << endl;
return;
}

如果字符串非空部分很长的话,上面的find_last_not_of显然缺乏效率,我们可以把trim函数改写为:

template <class T> void trim(std::basic_string<T>& s)
{
const char c = ' ';
s.erase(0, s.find_first_not_of(c));
basic_string<T>::reverse_iterator i =
std::find_if(s.rbegin(), s.rend(),
std::bind2nd(std::not_equal_to<T>(), c));
s.erase(i.base(), s.end());
}

不知道是否还有更好的方法。

----------------------------------------------
...全文
27 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
Elminster 2002-04-23
  • 打赏
  • 举报
回复
关于问题二,Matt Austern 在 CUJ Forum 上专文讨论过,相当详细。
关于问题三,嗯 …… 我想能不能讨论一下扩展情况?比如 string 两头既有空格又有‘\t’制表符,怎么把它们去掉?或者更一般些,给定一个字符集,将 string 两头在这个字符集中的字符都去掉?
hcpp 2002-04-23
  • 打赏
  • 举报
回复
领教领教。
babysloth 2002-04-23
  • 打赏
  • 举报
回复
谢谢大家的参与。
cber 2002-04-23
  • 打赏
  • 举报
回复
Elminster() :
对于问题三,在我上面给出的CppTips中已经由James Kanze搞定了,你可以去看看上面那一长串代码
>KANZE: James Kanze <kanze@gabi-soft.de>

>Not really. It doesn't consider other types of white space, nor
>other types of char.

Winner_Li 2002-04-22
  • 打赏
  • 举报
回复
Good!!
maoliao 2002-04-22
  • 打赏
  • 举报
回复
save!
xjl930 2002-04-22
  • 打赏
  • 举报
回复
STL的东西还是很值得探讨的,谢谢小懒虫虫精彩的帖子,收藏!!
jjyin7806 2002-04-22
  • 打赏
  • 举报
回复
GOOD
招RD和QA 2002-04-22
  • 打赏
  • 举报
回复
gzer
nicholas_87 2002-04-21
  • 打赏
  • 举报
回复
saved...
挺拔的劲松 2002-04-21
  • 打赏
  • 举报
回复
sc
vcmfc 2002-04-20
  • 打赏
  • 举报
回复
我的思跟是这样的,C中有个函数,名给忘了,也就是在一个char*上拷贝指定东东,估计没出异常安全,所以就是*p++加入API,不过代码还是比你多,你的最精练,对于string,你运用的好熟练,看来得闭关。
cber 2002-04-20
  • 打赏
  • 举报
回复
TITLE: trimming a standard string

(Source: comp.lang.c++.moderated, 18 Sep 2001)

WILSON: Bryan Wilson

> > I am new to C++ using MS Visual C++ 6.0 and trying to create a dll
> > to parse chunks from a flat .ASC file into a tab delimited .txt
> > file with leading and trailing spaces trimed off. Could someone
> > please show me an example of how to write the trim functionality??

FRITZSCHE: Albrecht Fritzsche <albrecht.fritzsche@alfabet.de>

> The std::string class already offers you enough functionality:
>
> std::string shortenString(const std::string& str) // untested code!!
> {
> std::string::size_type first = str.find_first_not_of(" ");
> std::string::size_type last = str.find_last_not_of(" ");
> return str.substr(first, last-first+1);
> }
>
> should give you a trimmed string

KANZE: James Kanze <kanze@gabi-soft.de>

Not really. It doesn't consider other types of white space, nor
other types of char.

There is a function in std::ctype that you'd expect to give you what
you need: scan_is. Regretfully, it doesn't work with iterators, only
charT*, so we are a bit handicapped. However, we can use std::find_if
by simply defining an appropriate predicate:

template< std::ctype_base::mask type , typename charT = char >
class Is : public std::unary_function< charT , bool >
{
public:
explicit Is( std::locale const& l )
: m_ctype( std::use_facet< std::ctype< charT > >( l ) )
{
}
bool operator()( charT ch ) const
{
return m_ctype.is( type , ch ) ;
}
private:
std::ctype< charT > const&
m_ctype ;
} ;

Given this, trim becomes just a simple return statement:

template< typename stringT >
stringT
trim( stringT const& s , std::locale const& l = std::locale() )
{
return
std::find_if(
s.begin() , s.end() ,
std::not1( Is< std::ctype_base::space ,
typename stringT::value_type >( l ) ) )
== s.end()
? stringT()
: stringT(
std::find_if(
s.begin() , s.end() ,
std::not1( Is< std::ctype_base::space ,
typename stringT::value_type >( l )
) ) ,
std::find_if(
s.rbegin() , s.rend() ,
std::not1( Is< std::ctype_base::space ,
typename stringT::value_type >( l )
) ).base() ) ;
}

OK, so the statement's a bit long. But the logic in it is actually
very simple, once you get through the cruft due to namespaces and the
template syntax. (Welcome to the wonderful world of generic
programming:-).)
x_zj 2002-04-20
  • 打赏
  • 举报
回复
to vcmfc:
那个函数是: strdup。
vcmfc 2002-04-19
  • 打赏
  • 举报
回复
最后一期,我是热衷于使用*p++的C方式来处理,高效安全。


这东东用STL,感觉就像用大炮打蚊子。
twist 2002-04-19
  • 打赏
  • 举报
回复
收藏
cber 2002-04-19
  • 打赏
  • 举报
回复
不错,不过我记得最后那个问题在CppTips上面有一个更据弹性的做法,但很复杂。你给出的那个做法差不多可以在大部分情况下使用了。
babysloth 2002-04-19
  • 打赏
  • 举报
回复
不用这样啊,老哥,呵呵。
就算是char*,恐怕也不容易,因为还涉及内存管理的问题。
vcmfc 2002-04-19
  • 打赏
  • 举报
回复
上面我说错了,是去掉string,而我以为是char*,真没长眼睛,收回我的话。

babysloth还是厉害,不得不佩服。
ljf1107 2002-04-19
  • 打赏
  • 举报
回复
不错!
加载更多回复(2)

70,020

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧