体验Visual C++.NET 2005中的STL

为了更好的使STL适合.NET开发,Visual C++产品组,在2005版的Visual C++中重新设计了STL,并命名为STL.NET,从Beta1版本的产品中开始提供。

  在STL.NET的设计中,STL的实现使用了CLI泛型和C++模版机制。2005版本的C++将加入C++/CLI动态编程的支持,应当会成为最能够满足程序员设计的语言。

  给予程序员丰富的选择

  总共有三个容器库可供程序员用于操作CLI类型,这三个容器库建于三种类型参数化模型之上。

  原先元素类型存储的Systems::Collection 库是基于CLI类型中的对象基类来实现的。如下的 ArrayList实现了IList接口。它代表类型对象的数组,在本例中用于控制String类型的元素。(这里采用版本2的语法来实现)

void objectCollection()
{
 using namespace System::Collections;
 ArrayList ^as = gcnew ArrayList;
 as->Add( "Pooh" ); as->Add( "Piglet" );
 as->Add( "Eeyore" ); as->Add( "Rabbit" );
 as->Sort();
 Console::WriteLine( "ArrayList holds {0} elements: ",as->Count );
 for ( int i = 0; i < as->Count; i++ )
  Console::WriteLine( as[ i ] );
  int index = as->IndexOf( "Pooh" );
  if ( index != -1 )
  {
   //需要一个清晰地downcast
   String^ item = safe_cast( as[ index ]);
   as->RemoveAt( index );
  }
  as->Remove( "Rabbit" );
  Console::WriteLine( "\nArrayList holds {0} elements: ",as->Count );
  IEnumerator^ is = as->GetEnumerator();
  while ( is->MoveNext() )
   Console::WriteLine( is->Current );
}

  现在我们引入了一个基于CLI泛型机制的新的容器库。可以在System::Collections::Generic 命名空间中找到。这是在Visual Studio 2005 Beta1中的实现,在最终的发布版当中可能会有所改变。Collection 是一个具体的泛型基类,用户们可以从其中派生自己特化的容器类。下面的样例与上面的例子作用相同,只是使用了新的容器库,

  STL.NET提供了一个与以往设计风格迥异的类型参数化模型,我们将在下个话题中谈到 。下面是String容器的实现。

#include
#include

void stlCollection()
{
 vector ^svec = gcnew vector;
 svec->push_back("Pooh"); svec->push_back("Piglet");
 svec->push_back("Eeyore"); svec->push_back("Rabbit");
 //泛型算法:sort
 sort( svec->begin(), svec->end() );
 Console::WriteLine( "Collection holds {0} elements: ",svec->size() );
 for ( int i = 0; i < svec->size(); i++ )
  Console::WriteLine( svec[ i ] );
  //泛型算法:find
  vector::iterator iter = find( svec->begin(), svec->end(), "Pooh" );
  if ( iter != svec->end() )
  {
   //不需要downcast……
   String ^item = *iter;
   svec->erase( iter );
  }
  //泛型算法: remove……
  remove( svec->begin(), svec->end(), "Rabbit" );
  Console::WriteLine( "\nCollection holds {0} elements:",svec->size() );
  IEnumerator ^is = svec->GetEnumerator();
  while ( is->MoveNext() )
  Console::WriteLine( is->Current );
 }

为什么要选用STL.NET?

  在我们深入STL.NET之前,让我们首先来简要地回答一个不可避免的问题:Visual C++程序员为什么要选用STL.NET容器类而不是语言中立的系统:Collections或者System::Collections::Generic 库?

  立即放弃System::Collections库和Visual Studio 2005决定提供泛型裤的原因是一样的:由于类型信息的丢失,经常会造成参数化对象模型非常的复杂并且不安全。在简单的使用中,例如在容器中装有16个或者更少的元素,进行冒泡排序的时候还可以使用。但当你的应用程序涉及到真实世界的问题的时候,你就必须要提供一个更为完善的解决方案了。

  所以,STL.NET和System::Collections::Generic库便成为如Visual C++这样的系统级程序设计语言的备选方案。为什么Visual C++程序员应当偏爱于STL.NET呢?这不就使我们的程序与其他的.NET语言隔离开了么?这是一个很现实的问题,并且也值得作出一个答复。

  回复之一是“可扩展性(extensibility)”。最初STL的设计模式是由Alex Stepanov发明的, 他将算法和容器存放在了不同的域空间中。这样用户就可以将所有容器都适用的算法添加到算法集当中去,或者将每个算法都可以应用的容器添加到容器集当中去。泛型库是一个更为传统的模型。这就引出了我们第二个回复。

  第二个回复是“统一性(unification)”。现在正在使用C++的程序员使用这个库和现有的代码的水平已经达到了专家水准。我们不仅仅希望能够提供一个对现有代码迁移的途径,同时也希望使程序员们积累下来的专家经验仍然适用。如果在你原来进行C++编程的时候依赖于STL,并且很难想象一个C++程序员不依赖于STL,那么它在.NET中的消失会使你感到是一个很大的失误—至少这是我曾经的体会。与我曾经交流过的很多C++专家都曾经提到过这个问题,并且因此表示对迁移到.NET持保留态度。

  第三个回复是“性能”。但是C++程序员对于讨论性能这个话题早已显得不愿意再提这些陈词滥调,我这里只是一笔带过—在后续的文章中将深入讨论。

  最后问题是。这些做的都非常棒并且非常好Stan, 但是这不是将C++程序员和C++/CLI程序与.NET社群的其它部分隔阂开了么?对于这个问题的回答,我认为是一个非常简单的“不”。STL.NET的体系架构师,包括Anson Tsao, Martyn Lovell, 和P.J. Plauger, 已经非常慎重地考虑了这个问题,通过对IEnumerator, IList, 和ICollection的支持,我们对于STL.NET能够和其它.NET 语言共同操作的能力非常有信心。我们将在后续的系列文章中深入的讨论。

  定义一个公共基础

  深入了解并使用STL.NET的方法有两种:一种途径是可以通过了解STL和STL.NET的区别来掌握。另外一种途径是通过了解他们有哪些共性。虽然那些有STL丰富使用经验的人来说似乎需要一张“区别清单”,然而这并不能使你从那些不熟悉的库的乌烟瘴气中逃离出来,所以说,当我们放慢脚步,深入这些或那些容器以及他们是如何与系统集合库(System collection libraries)互操作等这样的深奥角落的时候—虽然这些都是非常整洁优雅的,但我们直接的去了解这些新的内容不是更好么?至少在下面的简短介绍部分我希望大家是这样做的。通过这种方法,对于那些新手来说就可以对STL和STL.NET提供的参数化集合的扩展模型有一个了解。

  那么STL和STL.NET都有哪些共性呢?这两者都包括两个主要的组件:顺序式(Sequential)和关联式(associative)容器类型,以及一个泛型算法集。(是的,如果你是一个经验丰富的STL开发者,你就应当知道我下面要讨论什么。同样,两者具有同样的术语和背景,所以你得耐心点。) 泛型算法不直接操作容器类型。取而代之的是,我们使用了一个迭代器来成对的标识用于操作的元素范围。元素范围符号(正式的术语为左包含区间)如下所示:

// 读作:包含first直至但是不包括last

[ first, last )

  这表明了范围是从first开始以last结束但是不包含last。当first等于last的时候这个范围就是空了。

  顺序式容器中存储了单独类型元素的序列集。vector和list类型是两个主要的顺序式容器。(第三个顺序式容器是deque—发音deck—提供了vector同样的功能,但是用于对高效插入和删除第一个元素这种特殊情况。一般我们首选deque而不是vector,例如一个队列的实现。)

  我们在访问一个连续容器类型之前,我们必须包含进合适的头文件,如下所示:

#include

#include

#include

  这些头文件同时也包含了共享基类接口的声明,例如interface_vector,以及泛型在容器中的应用,例如generic_vector。

  关联式容器(associative container)支持对现有元素的显示和检索的高效查询。关联式容器类型中最主要的两个就是map和set。Map是一个key(键)/value(值)对:key用于查询,value用于存储和检索数据。举个例子来说,电话号码簿可以用map简单地表示出来:key是每一个人的名字,value是相关联的电话号码。

  map使用带下划线的树抽象来按照值升序排列条目。hash_map容器能够进行更为高效的检索排序。尽管如此,hash_map迭代也是某种程度上随机地访问元素。如果检索是map中的主要活动,就应首选hash_map容器。

  set包含一个单键值(key value) 并且支持元素是否存在的高效查询。例如,文本查询系统在建立文本词库的时候可能需要建立一个常用词语集并将之排除在文本外,例如the, and, but, 等等。程序将轮流的读取文本中的每一个词,检查它是否是拒绝接纳词汇集中的词汇,根据查询的结果,或者是忽略这个词,或者是将之存入数据库。除了set以外,还有hash_set 容器,它与map和hash_map有相同的特性。

  map和set只能包含一个键(key)。multimap和multiset 支持出现多个同样的键。还以我们的电话号码簿为例,我们可能需要将一个人列在多张表中。在这种情况下,我们就要使用multimap。同样也存在hash_multimap和hash_multiset。

  与这些容器类型相关联的头文件如下所示:

//用于map和multimap
#include
//用于set和multiset
#include
//用于hash_map和hash_multimap
#include
//用于hash_set和hash_multiset
#include
时间: 2024-08-30 01:43:41

体验Visual C++.NET 2005中的STL的相关文章

体验Visual C++ 2005的现代语言特性(1)

当年Visual Studio.NET 2003 C++编译器的面世,令无数C++语言爱好者都对此垂涎不已:它与ISO C++标准保持98%的一致--这比以前任何一个版本都更加接近,和一体化的语言支持特性,如局部模板特定化:同时也包括了增强的缓冲区安全检查和改进的编译器诊断功能.以往使用C#和Visual Basic.NET的开发者,通过简单的拖放操作,就能生成稳健的Windows窗体应用程序,如今,C++的开发者也加入了进来,而且,这个编译器还对Intel Pentium 4和AMD Athl

Visual C++ 2005中的突破性变化

Microsoft Visual C++ 2005是微软公司Visual Studio 2005开发套件中的一出重头戏,与前一个版本相比,其革新性的集成开发环境与C++编译器,带来了有许多改变.在本文中,主要讲解程序员在升级程序时,可能会遇到的一些不同之处及变化,而这些变化很可能会使老一点的程序不能通过编译.总之,这些变化绝不是偶然发生的,其背后都有强大的理论依据在支撑,所以,使用Visual C++的程序员,在升级之前,一定要弄清楚这些变化. Visual C++中已经发生的变化 微软Visu

体验Visual C++ 2005的现代语言特性(5)

可靠的安全 在2002年,Bill Gates宣布进行的可信赖计算,已对微软公司开发的所有产品带来了深刻的影响.Windows操作系统的开发者花了数月的时间来进行安全方面的训练及代码重审,带来的结果就是,Windows Server 2003成了该公司有史以来发布的最安全的操作系统.Microsoft Office 2003也包含了许多的安全功能,像IRM(Information Rights Management).加强的宏安全.Outlook中阻止下载HTML等等.而Visual C++ 2

体验Visual C++ 2005的现代语言特性(3)

It Just Works 在Visual Studio .NET 2003,C++的interop技术叫做IJW或者"It Just Works",在新版本中,已换成了更贴切的"Interop技术".那它的工作原理是怎样的呢?对程序中的每一个本地方法,编译器同时生成一个托管和非托管进入点,它们中只有一个是真正方法的实现,另一个则是转发器,可进行相应的转换和必要的调度.托管进入点通常是真正方法的实现,除非代码不能解释为MSIL或开发者使用"#pragma

体验Visual C++ 2005的现代语言特性(2)

新的Interop 在Visual Studio .NET 2003的所有基于 .NET Framework的语言当中,Visual C++ 2005提供了最好的interop功能.它可不像是纸上谈兵,如今具有了足够的能力来实现真实世界中的场景,一个最好的例子就是把Quake II移植到 .NET Framework平台上,而Visual C++ 2005则更加扩展了这项功能. 在本地和托管世界中,.NET有四种主要的方法可进行interop.对COM的interop可使用RCW(Runtime

Visual C++ 2005中混合代码的初始化

在Visual Studio .NET 2003中初始化混合DLLs很麻烦,需要手工干预.但在 Visual Studio 2005 中,Visual C++ 和 CLR 团队设计了一种新的初始化模型,这种新模型更简单,更自动化. Visual Studio .NET 2003 的根本问题在于将本地代码和托管代码一起置于单"池"中.DllMain 期间该池的运行是不安全的,托管代码根本就不能在这里运行. 新的模型将静态初始化汇集在两个单独的池中.一个池负责本地的静态初始化:另一个负责托

Visual C++ 2005中的XML注释

C#程序员可以用三个斜杠来开始XML格式的注释,而且编译器可以据此生成可用于自动生成帮助文档的XML文件.Visual C++ 2005中的编译器也支持了这个功能,而且对非托管函数也生效,前提是必须打开/clr和/DOC开关,并且不能使用/clr:oldSyntax开关编译. /**///////Use two bubble sort steps ///to show the performance information///of different function calls./// in

如何在Microsoft Visual Studio 2005中创建控制台应用程序

在 Visual Studio 2005 中创建控制台应用程序 在 Visual Studio 2005 中的"文件" 菜单上,指向"新建" 并单击"项目". 在"新建项目" 对话框中,选择一种语言,然后在"项目类型" 框中选择"Windows". 在"模板" 框中,选择"控制台应用程序" . 在"位置" 框中,键入指向应用程序

Visual C# 2005中如何以程控方式启动默认的浏览器

图 14-6所示是程序范例CH14_DemoForm006.cs的执行画面.我们发现,您只要单击窗体上的按钮,便会启动默认的浏览器并连接至指定的网址.相关程序代码编写于按钮的Click事件处理函数中,说明如下: 图 14-6 ◆请使用Process类的Start方法来启动默认的浏览器,并指定所要打开的URL.FTP或文件.因为Start方法是一个共享方法,因此您不需要建立Process类的实例就可以调用Start方法.比方说,下面的写法都是正确的: string target = "http:/