C++ 0X学习 (1)

先说下C++ 0x:

C++0x是一个新的C++标准
现行的C++标准是C++98,就是98年制定出来的
C++0x是计划在200X 制定,后来被定成C++09

美国AT&T贝尔实验室的本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)博士在20世纪80年代初期发明并实现了C++(最初这种语言被称作“C with Classes”)。一开始C++是作为C语言的增强版出现的,从给C语言增加类开始,不断的增加新特性。虚函数(virtual function)、运算符重载(operator overloading)、多重继承(multiple inheritance)、模板(template)、异常(exception)、RTTI、命名空间(name space)逐渐被加入标准。1998年国际标准组织(ISO)颁布了C++程序设计语言的国际标准ISO/IEC 1488-1998。C++是具有国际标准的编程语言,通常称作ANSI/ISO C++。1998年是C++标准委员会成立的第一年,以后每5年视实际需要更新一次标准,最近一次标准更新是在2009年,目前我们一般称该标准 C++0x

C++0x 新增了许多的特性,其中Visual Studio 2010 中的 Visual C++ 编译器,即 VC10, 包含了 4 个 C++ 0x 的语言特性:lambda 表达式自动类型推演(auto 关键字)(类似于C#的var关键字),静态断言(static_assert)右值引用(rvalue reference)。
本人感觉新标准似乎想把C#一些特性引用过来,这种做法会导致C++越变强大还是会成为一个冗杂的庞然大物呢。哎,学习中期待理解吧!下面从这些特性的学习总结开始。

Lambda 表达式

注(Lambda函数有一个函数体,但没有函数名。Lambda函数把函数指针和函数对象两者的最佳特性组合到了一起。因此,可以使用一个lambda函数来作为模板函数参数以代替一个函数对象,或者联合使用auto关键字来声明一个lambda类型的变量。)

C++0x 的语法还是比较简单。下面通过几个例子来介绍下。

先是通过 std::for_each 演示一个简单的例子:

std::for_each 和 lambda

 #include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>using namespace std;class LambdaTunctor
{
public:
 void operator()(int n)const
 {
  cout<<n<<" ";
 }
};int main()
{
 vector<int> v;
 for(int i=0;i<10;i++)
  v.push_back(i);
 for_each(v.begin(),v.end(),[](int n){cout<<n<<" ";});
 for_each(v.begin(),v.end(),LambdaTunctor()); int eventCount = 0;
 for_each(v.begin(),v.end(),[&eventCount](int n)
 {
  cout<<n;
  if(n%2 == 0)
  {
        cout<<"is event"<<endl;
     eventCount++;
  }
  else
  {
   cout<<"is odd"<<endl;
  }
 });
 cout<<"There are "<<eventCount<<
  "event numbers in the vector"<< endl;    system("pause");
 return 0;
}
 
 

首先,是不是发现 my_vector 的构造函数怪怪的呢。因为C++0x支持一种从C带来的初始化列表概念,

语法类似于 C 的 int array[] = {1, 2, 3, 4 ,5}。关于这个详细介绍,有机会下次再介绍

1.Lambda 的格式

对于这里的 lambda:[](int value) { std::cout << value << std::endl; }

从这里看出,lambda 是以 [] 开头的匿名函数。这个lambda 仅仅把参数打印出来,是一个 void 的函数。

对于需要返回值的 lambad,格式如下:[](int a, int b) { return a + b;}

在这里,返回值的类型是 decltype(a + b),decltype是一个新关键词,用于在编译期推导出类型。

如果想强制设定返回值类型,可以这样编写:[](int a, int b) -> int { return a + b;}

这里把返回值设置为 int 型。

2. [] 的表示方式

C++ 的 lambad 是支持闭包的。那么,是通过 [] 来表示 lambda 的变量集合,即闭包。

 

?
[]的表示
 
 
[] //没有定义变量,使用未定义的变量会导致错误。
[a, &b] //a以传值方式传入,b以引用方式传入
[&] // 表示在 lambda所使用到的变量,皆以引用方式传入
[=] // 表示在 lambda所使用到的变量,皆以传值方式传入
[&, a] //表示 a 以传值方式传入,其他都是以引用方式传入
[=, &a] // 表示 a 以引用方式传入,其他都是以传值方式传入
  
如果企图修改以值传入的变量,则编译的时候会报错(gcc 4.5)

下面来看看一个闭包的lambda例子:

 

?

lambda的闭包

#include <iostream> 
#include <vector> 
#include <algorithm> 
  
int main() { 
  
    std::vector<int> my_vector({1, 2, 3, 4 ,5}); 
  
    int total = 0; 
  
    std::for_each(my_vector.begin(), my_vector.end(), 
        [&total](int value) { 
            total++; 
        }); 
  
    std::cout << "total:" << total << std::endl; 
  
    return 0; 
} 


 
 

这里的输出结果是: total:5

3.涉及 this 指针的使用

在成员函数中涉及到对象的 this 指针,必须显式地传入lambda函数,否则成员函数的lambda函数无法使用任何对象的变量或者函数,格式如下:

[this]() { this->call_function(); }

auto 关键字

auto 这个关键字来自 C++ 98 标准。在 C++ 98 中它没有什么作用,C++ 0x 中“借用”它来作为自动类型推演(automatic type deduction)。当 auto 出现在声明中时,它表示“请用初始化我的表达式类型作为我的类型”,例如下面代码:

#include <iostream> #include <map> #include <ostream> #include <regex> #include <string>

using namespace std; using namespace std::tr1;

int main() { map<string, string> m;

const regex r("(\\w+) (\\w+)");

for (string s; getline(cin, s); ) { smatch results;

if (regex_match(s, results, r)) {  m[results[1]] = results[2]; } }

for (auto i = m.begin(); i != m.end(); ++i) { cout << i->second << " are " << i->first << endl; }

运行结果如下:

cute kittens
ugly puppies
evil goblins
^Z
kittens are cute
goblins are evil
puppies are ugly

上面例子中i的类型在编译时推演为 map::iterator, 有了 auto 关键字你再也不用写又长又烦的代码了。(注意 m.begin() 返回类型是 iterator, 而不是 const_iterator, 因为这里的 m 并不是 const。C++0x 中的 cbegin() 能够解决这个问题,它返回 non-const 容器的 const 迭代器。)



 

 

你可能感兴趣的:(C++,vector,iterator,lambda,each,overloading)