??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品久久久久aaaa,久久国产成人亚洲精品影院,久久天天躁狠狠躁夜夜2020一http://m.shnenglu.com/tianbianlan/zh-cnMon, 12 May 2025 19:40:08 GMTMon, 12 May 2025 19:40:08 GMT60 Sequoiadb与sparkҎ(gu)步骤http://m.shnenglu.com/tianbianlan/archive/2015/05/26/210753.html天边?/dc:creator>天边?/author>Tue, 26 May 2015 09:13:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2015/05/26/210753.htmlhttp://m.shnenglu.com/tianbianlan/comments/210753.htmlhttp://m.shnenglu.com/tianbianlan/archive/2015/05/26/210753.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/210753.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/210753.html hive.aux.jars.path file:///ocsdev/hadoop/apache-hive-1.1.0-bin/lib/hive-sequoiadb-apache.jar,file:///ocsdev/hadoop/apache-hive-1.1.0-bin/lib/sequoiadb.jar Sequoiadb store handler jar file 2.配置SPARK_CLASSPATH export SPARK_CLASSPATH=/path/to/spark/lib/sequoiadb-driver-1.12.jar:/path/to/spark/lib/lib/spark-sequoiadb_2.10-1.12.jar:/ocsdev/hadoop/spark-1.3.1-bin-hadoop2.6/lib://path/to/spark/lib/mysql-connector-java-5.1.5-bin.jar 3.sequoiadb-driver-1.12.jar、spark-sequoiadb_2.10-1.12.jar拯到spark的lib目录下; 4.hive-site.xml配置元数据存储方? hive.metastore.local true javax.jdo.option.ConnectionURL jdbc:mysql://192.168.0.103:3306/hive?characterEncoding=UTF-8 javax.jdo.option.ConnectionDriverName com.mysql.jdbc.Driver javax.jdo.option.ConnectionUserName hive javax.jdo.option.ConnectionPassword hive 5.创徏S(chng)equoiadb集合映射关系Q? ./spark_sql >CREATE table lw_test_sdb (id int, r5 double) using com.sequoiadb.spark OPTIONS ( host '192.168.0.103:11810,192.168.0.104:11810,192.168.0.102:11810', collectionspace 'hj', collection 'aws_min',username '',password ''); 6.查询数据 >select * from lw_test_sdb NULL 0.0 23 23.4 12 34.5 Time taken: 0.825 seconds, Fetched 3 row(s)

]]>
RDD初探http://m.shnenglu.com/tianbianlan/archive/2015/04/18/210383.html天边?/dc:creator>天边?/author>Sat, 18 Apr 2015 14:16:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2015/04/18/210383.htmlhttp://m.shnenglu.com/tianbianlan/comments/210383.htmlhttp://m.shnenglu.com/tianbianlan/archive/2015/04/18/210383.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/210383.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/210383.html

]]>
[转]The Biggest Changes in C++11 http://m.shnenglu.com/tianbianlan/archive/2013/05/05/199992.html天边?/dc:creator>天边?/author>Sun, 05 May 2013 13:26:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2013/05/05/199992.htmlhttp://m.shnenglu.com/tianbianlan/comments/199992.htmlhttp://m.shnenglu.com/tianbianlan/archive/2013/05/05/199992.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/199992.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/199992.html

源文章来自前C++标准委员?sh)(x)?nbsp;Danny Kalev ?nbsp;The Biggest Changes in C++11 (and Why You Should Care)Q赖勇浩做了(jin)一?a target="_blank">中文译在这?/a>。所以,我就不翻译了(jin)Q我在这里仅Ҏ(gu)中提到的q些变化“q问Z么要引入q些变化”的一个探讨,只有知道Z(jin)什么,用在什么地方,我们才能真正学到q个知识。而以此你可以更深入地?jin)解q些变化。所以,本文不是译。因为写得有些仓?j),所以难免有问题Q还请大家指正?/p>

Lambda 表达?/h4>

Lambda表达式来源于函数式编E,说白׃(jin)是在用的地方定义函数Q有的语a?#8220;闭包”Q如?lambda 函数没有传回?例如 void )Q其回返cd可被完全忽略?定义在与 lambda 函数相同作用域的变量参考也可以被用。这U的变量集合一般被UC closureQ闭包)(j)。我在这里就不再讲这个事?jin)。表辑ּ的简单语法如下,

1
[capture](parameters)->return_type {body}

原文的作者给Z(jin)下面的例子:(x)

1
2
3
4
5
6
7
8
9
10
int main()
{
   char s[]="Hello World!";
   int Uppercase = 0; //modified by the lambda
   for_each(s, s+sizeof(s), [&Uppercase] (char c) {
    if (isupper(c))
     Uppercase++;
    });
 cout << Uppercase << " uppercase letters in: " << s <<endl;
}

在传l的STL中for_each() q个玩意最后那个参数需要一?#8220;函数对象”Q所谓函数对象,其实是一个classQ这个class重蝲?jin)operator()Q于是这个对象可以像函数的式L(fng)使用。实C个函数对象ƈ不容易,需要用templateQ比如下面这个例子就是函数对象的单例子(实际的实现远比这个复杂)(j)Q?/p>

1
2
3
4
5
6
7
8
9
template <class T>
class less
{
public:
    bool operator()(const T&l, const T&r)const
    {
        return l < r;
    }
};

所以,C++引入Lambda的最主要原因是1Q可以定义匿名函敎ͼ2Q编译器?x)把其{成函数对?/strong>。相信你?x)和我一P?x)疑问?f)什么以前STL中的ptr_fun()q个函数对象不能用?Qptr_fun()是把一个自然函数{成函数对象的Q。原因是Qptr_fun() 的局限是其接收的自然函数只能??个参数?/p>

那么Q除?jin)方便外Qؓ(f)什么一定要使用Lambda呢?它比传统的函数或是函数对象有什么好处呢Q我个h所理解的是Q这U函Cq以?#8220;闭包”Q就是因为其限制?jin)别人的讉KQ更U有。也可以认ؓ(f)他是一ơ性的Ҏ(gu)。Lambda表达式应该是z的Q极U有的,Z(jin)更易的代码和更方便的~程?/p>

自动cd推导 auto

在这一节中Q原文主要介l了(jin)两个关键?auto ?deltypeQ示例如下:(x)

1
2
3
4
auto x=0; //x has type int because 0 is int
auto c='a'; //char
auto d=0.5; //double
auto national_debt=14400000000000LL;//long long

auto 最大的好处是让代码简z,其是那些模板类的声明,比如QSTL中的容器的P代子cd?/p>

1
vector<int>::const_iterator ci = vi.begin();

可以变成Q?/p>

1
auto ci = vi.begin();

模板q个Ҏ(gu)让C++的代码变得很难读Q不信你可以看看STL的源码,那是一个ؕ啊。用auto必需一个初始化|~译器可以通过q个初始化值推导出cd。因为auto是来化模板类引入的代码难ȝ问题Q如上面的示例,iterationq种cd最适合用auto的,但是Q我们不应该把其滥用?/p>

比如下面的代码的可读性就降低?jin)。因为,我不知道P(yng)rocessDataq回什么?int? bool? q是对象Q或是别的什么?q让你后面的E序不知道怎么做?/p>

1
auto obj = ProcessData(someVariables);

但是下面的程序就没有问题Q因为pObject的型别在后面的new中有?jin)?/p>

1
auto pObject = new SomeType<OtherType>::SomeOtherType();

自动化推?decltype

关于 decltype 是一个操作符Q其可以评估括号内表辑ּ的类型,其规则如下:(x)

  1. 如果表达式e是一个变量,那么是q个变量的类型?/li>
  2. 如果表达式e是一个函敎ͼ那么是q个函数q回值的cd?/li>
  3. 如果不符??Q如果e是左|cd为TQ那么decltype(e)是T&Q如果是叛_|则是T?/li>

原文l出的示例如下,我们可以看到Q这个让的确我们的定义变量省?jin)很多事?/p>

1
2
3
const vector<int> vi;
typedef decltype (vi.begin()) CIT;
CIT another_const_iterator;

q有一个适合的用法是用来typedef函数指针Q也?x)省很多事。比如:(x)

1
2
3
decltype(&myfunc) pfunc = 0;
 
typedef decltype(&A::func1) type;

auto ?decltype 的差别和关系

Wikipedia 上是q么说的Q关于decltype的规则见上)(j)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <vector>
 
int main()
{
    const std::vector<int> v(1);
    auto a = v[0];        // a 的类型是 int
    decltype(v[0]) b = 1; // b 的类型是 const int&, 因ؓ(f)函数的返回类型是
                          // std::vector<int>::operator[](size_type) const
    auto c = 0;           // c 的类型是 int
    auto d = c;           // d 的类型是 int
    decltype(c) e;        // e 的类型是 int, 因ؓ(f) c 的类型是int
    decltype((c)) f = c;  // f 的类型是 int&, 因ؓ(f) (c) 是左?/code>
    decltype(0) g;        // g 的类型是 int, 因ؓ(f) 0 是右?/code>
}

如果auto ?decltype 在一起用会(x)是什么样子?能看下面的示例,下面q个CZ也是引入decltype的一个原?#8212;—让C++有能力写一?“ forwarding function 模板”Q?/p>

1
2
3
template< typename LHS, typename RHS>
  auto AddingFunc(const LHS &lhs, const RHS &rhs) -> decltype(lhs+rhs)
{return lhs + rhs;}

q个函数模板看v来相当费解,其用C(jin)auto ?decltype 来扩展了(jin)已有的模板技术的不。怎么个不_Q在上例中,我不知道AddingFunc?x)接收什么样cd的对象,q两个对象的 + 操作W返回的cd也不知道Q老的模板函数无法定义AddingFuncq回值和q两个对象相加后的返回值匹配,所以,你可以用上q的q种定义?/p>

l一的初始化语法

C/C++的初始化的方法比较,C++ 11 用大括号l一?jin)这些初始化的方法?/p>

比如QPOD的类型?/p>

1
2
int arr[4]={0,1,2,3};
struct tm today={0};

关于POD相说两句Q所谓P(yng)OD是Plain Old DataQ当class/struct?em>极简?trivial)、属?em>标准布局(standard-layout)Q以?qing)他的所有非?rn)态(non-staticQ成员都是PODӞ?x)被视?f)POD。如Q?/p>

1
2
3
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

POD的初始化有点怪,比如上例Qnew A; 和new A(); 是不一L(fng)Q对于其内部的mQ前者没有被初始化,后者被初始化了(jin)Q不?的编译器行ؓ(f)不一PVC++和GCC不一P(j)。而非POD的初始化Q则都会(x)被初始化?/p>

从这点可以看出,C/C++的初始化问题很奇怪,所以,在C++ 2011版中做?jin)统一。原文作者给Z(jin)如下的示例:(x)

1
2
3
4
5
6
7
8
9
C c {0,0}; //C++11 only. 相当? C c(0,0);
 
int* a = new int[3] { 1, 2, 0 }; /C++11 only
 
class X {
    int a[4];
    public:
        X() : a{1,2,3,4} {} //C++11, member array initializer
};

容器的初始化Q?/p>

1
2
3
4
5
// C++11 container initializer
vector<string> vs={ "first", "second", "third"};
map singers =
{ {"Lady Gaga", "+1 (212) 555-7890"},
{"Beyonce Knowles", "+1 (212) 555-0987"}};

q支持像Java一L(fng)成员初始化:(x)

1
2
3
4
5
6
class C
{
   int a=7; //C++11 only
 public:
   C();
};

Delete ?Default 函数

我们知道C++的编译器在你没有定义某些成员函数的时候会(x)l你的类自动生成q些函数Q比如,构造函敎ͼ拯构造,析构函数Q赋值函数。有些时候,我们不想要这些函敎ͼ比如Q构造函敎ͼ因ؓ(f)我们惛_实现单例模式。传l的做法是将其声明成privatecd?/p>

在新的C++中引入了(jin)两个指示W,delete意ؓ(f)告诉~译器不自动产生q个函数Qdefault告诉~译器生一个默认的。原文给Z(jin)下面两个例子Q?/p>

1
2
3
4
5
struct A
{
    A()=default; //C++11
    virtual ~A()=default; //C++11
};

再如delete

1
2
3
4
5
6
7
struct NoCopy
{
    NoCopy & operator =( const NoCopy & ) = delete;
    NoCopy ( const NoCopy & ) = delete;
};
NoCopy a;
NoCopy b(a); //compilation error, copy ctor is deleted

q里Q我惌一下,Z么我们需要defaultQ我什么都不写不就是default吗?不全然是Q比如构造函敎ͼ因ؓ(f)只要你定义了(jin)一个构造函敎ͼ~译器就不会(x)l你生成一个默认的?jin)。所以,Z(jin)要让默认的和自定义的共存Q才引入q个参数Q如下例所C:(x)

1
2
3
4
5
struct SomeType
{
 SomeType() = default; // 使用~译器生成的默认构造函?/code>
 SomeType(OtherType value);
};

关于deleteq有两个有用的地Ҏ(gu)

1Q让你的对象只能生成在栈内存?sh)?x)

1
2
3
struct NonNewable {
    void *operator new(std::size_t) = delete;
};

2Q阻止函数的其Ş参的cd调用Q(若尝试以 double 的Ş参调?nbsp;f()Q将?x)引发编译期错误Q?~译器不?x)自动?double 形参转型?int 再调?code>f()Q如果传入的参数是doubleQ则?x)出现编译错误?j)

1
2
void f(int i);
 void f(double) = delete;

nullptr

C/C++的NULL宏是个被有很多潜在BUG的宏。因为有的库把其定义成整?Q有的定义成 (void*)0。在C的时代还好。但是在C++的时代,q就?x)引发很多问题。你可以上网看看。这是ؓ(f)什么需?nbsp;nullptr 的原因?nbsp;nullptr 是强cd的?/p>

1
2
3
4
5
6
void f(int); //#1
void f(char *);//#2
//C++03
f(0); //二义?/code>
//C++11
f(nullptr) //无二义性,调用f(char*)

所以在新版中请?nullptr 初始化指针?/p>

委托构?/h4>

在以前的C++中,构造函C间不能互相调用,所以,我们在写q些怼的构造函数里Q我们会(x)把相同的代码攑ֈ一个私有的成员函数中?/p>

1
2
3
4
5
6
7
8
9
10
class SomeType {
private:
  int number;
  string name;
  SomeType( int i, string&amp; s ) : number(i), name(s){}
public:
  SomeType( )               : SomeType( 0, "invalid" ){}
  SomeType( int i )         : SomeType( i, "guest" ){}
  SomeType( string&amp; s ) : SomeType( 1, s ){ PostInit(); }
};

但是Qؓ(f)?jin)方便ƈ不?#8220;委托构?#8221;q个事出玎ͼ最主要的问题是Q基cȝ构造不能直接成为派生类的构造,q是基cȝ构造函数够?jin),zc还要自己写自己的构造函敎ͼ(x)

1
2
3
4
5
6
7
8
9
10
11
class BaseClass
{
public:
  BaseClass(int iValue);
};
 
class DerivedClass : public BaseClass
{
public:
  using BaseClass::BaseClass;
};

上例中,zcL动(h)承基cȝ构造函敎ͼ ~译器可以用基cȝ构造函数完成派生类的构造?而将基类的构造函数带入派生类的动?无法选择性地部分带入Q?所以,要不是l承基类全部的构造函敎ͼ要不是一个都不(h)?不手动带??此外Q若牉|到多重(h)承,从多个基cȝ(h)承而来的构造函C可以有相同的函数{֐(signature)?而派生类的新加入的构造函C不可以和l承而来的基cL造函数有相同的函数签名,因ؓ(f)q相当于重复声明。(所谓函数签名就是函数的参数cd和顺序不Q?/p>

叛_引用和move语义

在老版的C++中,临时性变量(UCؓ(f)叛_?#8221;R-values”Q位于赋值操作符之右Q经常用作交换两个变量。比如下面的CZ中的tmp变量。示例中的那个函数需要传递两个string的引用,但是在交换的q程中生了(jin)对象的构造,内存的分配还有对象的拯构造等{动作,成本比较高?/p>

1
2
3
4
5
6
void naiveswap(string &amp;a, string &amp;b)
{
 string temp = a;
 a=b;
 b=temp;
}

C++ 11增加一个新的引用(referenceQ类型称作右值引用(R-value referenceQ,标记?tt>typename &&。他们能够以non-const值的方式传入Q允许对象去改动他们。这修正允许特定对象创造出move语义?/p>

举例而言Q上面那个例子中QstringcM保存?sh)(jin)一个动态内存分存的char*指针Q如果一个string对象发生拯构造(如:(x)函数q回Q,stringc里的char*内存只能通过创徏一个新的(f)时对象,q把函数内的对象的内存copy到这个新的对象中Q然后销毁(f)时对象及(qing)其内存?strong>q是原来C++性能上重点被批评的事?/p>

能过叛_引用,string的构造函数需要改?#8220;move构造函?#8221;Q如下所C。这样一来,使得Ҏ(gu)?span style="font-family: monospace">stirng的右值引用可以单U地从右值复制其内部C-style的指针到新的stringQ然后留下空的右倹{这个操作不需要内存数l的复制Q而且I的暂时对象的析构也不会(x)释放内存。其更有效率?/p>

1
2
3
4
5
class string
{
    string (string&&); //move constructor
    string&& operator=(string&&); //move assignment operator
};

The C++11 STL中广泛地使用?jin)右值引用和move语议。因此,很多法和容器的性能都被优化?jin)?/p>

C++ 11 STL 标准?/h4>

C++ STL库在2003q经历了(jin)很大的整Ҏ(gu)?nbsp;Library Technical Report 1 (TR1)?TR1 中出C(jin)很多新的容器c?(unordered_set, unordered_map, unordered_multiset, ?nbsp;unordered_multimap) 以及(qing)一些新的库支持诸如Q正则表辑ּQ?tuplesQ函数对象包装,{等?C++11 批准?TR1 成ؓ(f)正式的C++标准Q还有一些TR1 后新加的一些库Q从而成Z(jin)新的C++ 11 STL标准库。这个库主要包含下面的功能:(x)

U程?/h5>

q们׃多说?jin),以前的STL饱受U程安全的批评。现在好 ?jin)。C++ 11 支持U程cM(jin)。这涉?qing)两个部分?x)W一、设计一个可以多个U程在一个进E中共存的内存模型;W二、ؓ(f)U程之间的交互提供支持。第二部分将q序库提供支持。大家可以看?a target="_blank">promises and futuresQ其用于对象的同步?nbsp;async() 函数模板用于发vq发dQ?nbsp;thread_local 为线E内的数据指定存储类型。更多的东西Q可以查?Anthony Williams?nbsp;Simpler Multithreading in C++0x.

新型指针

C++98 的知能指针是 auto_ptrQ?在C++ 11中被废弃?jin)?/code>C++11  引入?jin)两个指针类Q?nbsp;shared_ptr ?unique_ptr?shared_ptr只是单纯的引用计数指针,unique_ptr 是用来取?code>auto_ptr?nbsp;unique_ptr 提供 auto_ptr 大部份特性,唯一的例外是 auto_ptr 的不安全、隐性的左值搬UR不?nbsp;auto_ptrQ?code>unique_ptr 可以存放?C++0x 提出的那些能察觉搬移动作的容器之中?/p>

Z么要q么qԌ大家可以看看《More Effective C++》中?auto_ptr的讨论?/p>

新的法

定义?jin)一些新的算法:(x) all_of(), any_of() ?nbsp;none_of()?/code>

1
2
3
4
5
6
7
8
#include &lt;algorithm&gt;
//C++11 code
//are all of the elements positive?
all_of(first, first+n, ispositive()); //false
//is there at least one positive element?
any_of(first, first+n, ispositive());//true
// are none of the elements positive?
none_of(first, first+n, ispositive()); //false

使用新的copy_n()法Q你可以很方便地拯数组?/p>

1
2
3
4
5
#include &lt;algorithm&gt;
int source[5]={0,12,34,50,80};
int target[5];
//copy 5 elements from source to target
copy_n(source,5,target);

使用 iota() 可以用来创徏递增的数列。如下例所C:(x)

1
2
3
4
5
include &lt;numeric&gt;
int a[5]={0};
char c[3]={0};
iota(a, a+5, 10); //changes a to {10,11,12,13,14}
iota(c, c+3, 'a'); //{'a','b','c'}

MQ看下来QC++11 q是很学院派Q很多实用的东西q是没有Q比如:(x) XMLQsocketsQreflectionQ当然还有垃圑֛收。看来要{到C++ 20?jin)。呵c(din)不qC++ 11在性能上还是很快。参?Google’s benchmark tests。原文还引用Stroustrup 的观点:(x)C++11 是一门新的语a——一个更好的 C++?/p>

如果把所有的改变都列出来Q你?x)发现真多啊。我估计C++ Primer那本书的厚度要增加至?0%以上。C++的门槛会(x)不会(x)来高?sh)(jin)呢Q我不知道,但我个h觉得q门语言的确是变得越来越令h望而却步了(jin)。(惌v?jin)某人和我说的一句话——学技术真的是太篏?jin),q是搞方法论好؜些?Q?/p>

]]>
各编译器对于C++11新特性的支持情况http://m.shnenglu.com/tianbianlan/archive/2013/05/05/199991.html天边?/dc:creator>天边?/author>Sun, 05 May 2013 13:11:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2013/05/05/199991.htmlhttp://m.shnenglu.com/tianbianlan/comments/199991.htmlhttp://m.shnenglu.com/tianbianlan/archive/2013/05/05/199991.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/199991.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/199991.htmlhttp://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport
The following table lists C++0x features and their support in popular compilers.

Status Of C++ 0x Language Features in Compilers

C++ 0x FEATURE

PAPER(S)

HP aCC

EDG eccp

GCC

Intel C++

MSVC

IBM XLC++

Sun/ Oracle C++

Embarcadero C++ Builder

Digital Mars C++

Clang

alignas

N2341

4.8

3.0

alignof

N2341

4.5

Yes

2.9

Atomic operations

N2427

4.4

13.0

11.0

3.1

auto

v0.9: N1984, v1.0: N2546

4.1(v0.9)

4.4(v1.0)

11.0(v0.9)

10.0(v0.9)

11.1 (V1.0)

Yes

C99 preprocessor

N1653

4.3

11.1

10.1

5.9

Yes

Yes

Concepts [removed]

N2617

ConceptGcc


constexpr

N2235

4.6

13.0

12.1

3.1

decltype

v1.0: N2343, v1.1: N3276

4.1(v1.0)

4.3(v1.0) 4.8.1(v1.1)

11.0(v1.0)

10.0(v1.0), 11.0(v1.1)

11.1 (V1.0)

Yes

2.9

Defaulted And Deleted Functions

N2346

4.1

4.4

12.0

3.0

Delegating Constructors

N1986

4.7


11.0 nov'12

11.1

3.0

Explicit conversion operators

N2437

4.5

13.0

11.0 nov'12

12.1

Yes

3.0

Extended friend Declarations

N1791

4.1

4.7

11.0

10.0***

V1R11,11.1

2.9

extern template

N1987

3, 5, 6

3.3

9

6.0

V1R11,11.1

Yes

Yes

Forward declarations for enums

N2764

4.6

11.0

12.1

3.1

Inheriting Constructors

N2540

4.8



Initializer Lists

N2672

4.4

13.0

11.0 nov'12

3.1

Lambda expressions and closures

v0.9: N2550, v1.0: N2658, v1.1: N2927

4.1(v0.9)

4.5(v1.1)

11.0(v0.9)
12.0(v1.0)

10.0(v1.0), 11.0(v1.1)

3.1

Local and Unnamed Types as Template Arguments

N2657

4.5

12.0

10.0

2.9

long long

N1811

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Namespace Association

N2535

4.4


11.1

2.9

New character types

N2249

4.4

2.9

New function declaration syntax for deduced return types

N2541

4.1

4.4

12.1

10.0

12.1

2.9

nullptr

N2431

4.6

12.1*

10.0

2.9

Unicode String Literals

N2442

4.4

11.0*

5.7

Yes

3.0

Raw String Literals

N2442

4.5


11.0 nov'12

Yes

User-defined Literals

N2765

4.7

3.1

Right Angle Brackets

N1757

4.1

4.3

11.0

8.0

12.1

Yes

R-Value References, std::move

v1.0: N2118, v2.0: N2844, v2.1: N2844+, v3.0: N3053

4.1(v1.0)

4.3(v1.0)
4.5(v2.1)
4.6(v3.0)

11.1(v1.0)
12.0(v2.0)

10.0(v2.0), 11.0(v2.1)

12.1(v2.1)

Yes

Yes

static_assert

N1720

4.1

4.3

11.0

10.0

11.1

Yes

2.9

Strongly-typed enums

N2347

4.4

12.0

11.0

12.1

Yes

2.9

Template aliases

N2258

4.7

12.1

3.0

Thread-Local Storage

N2659

4.8 (4.4****)

11.1***

10.0***

5.9***

2.9****

Unrestricted Unions

N2544

4.6


3.0

Built-in Type Traits

N1836

6.16

4.0

4.3

10.0

8.0

Yes

3.0

Variadic Templates

v0.9: N2242, v1.0: N2555

4.1(v0.9)

4.3(v0.9) 4.4(v1.0)

12.1(v0.9)

11.0 nov'12

11.1 (v0.9)

2.9(1.0)

Range-based for-loop

N2930

4.6

13.0

11.0

3.0

override and final

v0.8: N2928, v0.9: N3206, v1.0: N3272

4.7

12.0(v0.8)***

8.0(v0.8)*** 11.0(v1.0)

2.9

Attributes

N2761

4.8

12.1

ref-qualifiers

N2439

4.8.1

2.9

Non-static data member initializers

N2756

4.7

3.0

Dynamic initialization and destruction with concurrency (Magic statics)

N2660

4.3

?

2.9

* — 1) unicode string literals is a feature of the EDG frontend, but it is undocumented at Intel C++ compiler (/Qoption,cpp,"--uliterals" option enables it)



]]>
gprof——GNU性能分析工具 http://m.shnenglu.com/tianbianlan/archive/2013/04/22/199639.html天边?/dc:creator>天边?/author>Mon, 22 Apr 2013 08:39:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2013/04/22/199639.htmlhttp://m.shnenglu.com/tianbianlan/comments/199639.htmlhttp://m.shnenglu.com/tianbianlan/archive/2013/04/22/199639.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/199639.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/199639.html转蝲?/em>http://www.cnblogs.com/feisky/archive/2010/03/09/1681997.html

gprof介绍

gprof是GNU profiler工具。可以显C程序运行的“flat profile”Q包括每个函数的调用ơ数Q每个函数消耗的处理器时间。也可以昄“调用?#8221;Q包括函数的调用关系Q每个函数调用花费了(jin)多少旉。还可以昄“注释的源代码”Q是E序源代码的一个复本,标记有程序中每行代码的执行次数?/p>

为gprof~译E序


在编译或链接源程序的时候在~译器的命o(h)行参C加入“-pg”选项Q编译时~译器会(x)自动在目标代码中插入用于性能试的代码片断,q些代码在程序在q行旉集ƈ记录函数的调用关pd调用ơ数Q以?qing)采集ƈ记录函数自n执行旉和子函数的调用时_(d)E序q行l束后,?x)在E序退出的路径下生成一个gmon.out文g。这个文件就是记录ƈ保存?sh)来的监控数据。可以通过命o(h)行方式的gprof或图形化的Kprof来解读这些数据ƈ对程序的性能q行分析。另外,如果x(chng)看库函数的profilingQ需要在~译是再加入“-lc_p”~译参数代替“-lc”~译参数Q这L(fng)序会(x)链接libc_p.a库,才可以生库函数的profiling信息。如果想执行一行一行的profilingQ还需要加?#8220;-g”~译参数?br />例如如下命o(h)行:(x)gcc -Wall -g -pg -lc_p example.c -o example

Gprof基本用法Q?/em>

1Q?使用 -pg ~译和链接你的应用程序?/p>

2Q?执行你的应用E序使之生成供gprof 分析的数据?

3Q?使用gprof E序分析你的应用E序生成的数据?

$gprof -b a.out gmon.out      
Flat profile:

Each sample counts as 0.01 seconds.
no time accumulated

  %   cumulative   self              self     total          
time   seconds   seconds    calls  Ts/call  Ts/call  name   
  0.00      0.00     0.00        1     0.00     0.00  function

                        Call graph

granularity: each sample hit covers 2 byte(s) no time propagated

index % time    self  children    called     name
                0.00    0.00       1/1           main [8]
[1]      0.0    0.00    0.00       1         function [1]
-----------------------------------------------

Index by function name

   [1] function

gprof产生的信?/h1>


%                        the percentage of the total running time of the
time                     program used by this function.
                           函数使用旉占所有时间的癑ֈ比?br />cumulative          a running sum of the number of seconds accounted
seconds             for by this function and those listed above it.
                           函数和上列函数篏计执行的旉?br />self                    the number of seconds accounted for by this
seconds             function alone.  This is the major sort for this
                          listing.
                          函数本n所执行的时间?br />calls                   the number of times this function was invoked, if
                          this function is profiled, else blank.
                          函数被调用的ơ数
self                   the average number of milliseconds spent in this
ms/call               function per call, if this function is profiled,
                         else blank.
                          每一ơ调用花费在函数的时间microseconds?br />total                  the average number of milliseconds spent in this
ms/call               function and its descendents per call, if this
                          function is profiled, else blank.
                          每一ơ调用,p在函数及(qing)其衍生函数的q_旉microseconds?br />name                 the name of the function.  This is the minor sort
                          for this listing. The index shows the location of
                          the function in the gprof listing. If the index is
                          in parenthesis it shows where it would appear in
                          the gprof listing if it were to be printed.
                          函数?/p>

命o(h)格式

gprof [可执行文件] [gmon.out文g] [其它参数]

Ҏ(gu)号中的内容可以省略。如果省略了(jin)“可执行文?#8221;Qgprof?x)在当前目录下搜索a.out文g作ؓ(f)可执行文Ӟ而如果省略了(jin)gmon.out文gQgprof也会(x)在当前目录下Lgmon.out。其它参数可以控制gprof输出内容的格式等信息。最常用的参数如下:(x)

l -b 不再输出l计图表中每个字D늚详细描述?

l -p 只输出函数的调用图(Call graph的那部分信息Q?

l -q 只输出函数的旉消耗列表?

l -e Name 不再输出函数Name ?qing)其子函数的调用图(除非它们有未被限制的其它父函敎ͼ?j)。可以给定多?-e 标志。一?-e 标志只能指定一个函数?

l -E Name 不再输出函数Name ?qing)其子函数的调用图,此标志类g -e 标志Q但它在L间和癑ֈ比时间的计算中排除了(jin)由函数Name ?qing)其子函数所用的旉?

l -f Name 输出函数Name ?qing)其子函数的调用图。可以指定多?-f 标志。一?-f 标志只能指定一个函数?

l -F Name 输出函数Name ?qing)其子函数的调用图,它类g -f 标志Q但它在L间和癑ֈ比时间计中仅用所打印的例E的旉。可以指定多?-F 标志。一?-F 标志只能指定一个函数?F 标志覆盖 -E 标志?

l -z 昄使用ơ数为零的例E(按照调用计数和篏U时间计)(j)?

不过,gprof不能昄对象之间的(h)承关p?q也是它的弱?



]]>
【{】浅析系l的大小端模?http://m.shnenglu.com/tianbianlan/archive/2012/01/19/164364.html天边?/dc:creator>天边?/author>Thu, 19 Jan 2012 03:39:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2012/01/19/164364.htmlhttp://m.shnenglu.com/tianbianlan/comments/164364.htmlhttp://m.shnenglu.com/tianbianlan/archive/2012/01/19/164364.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/164364.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/164364.html

 

据的高(sh)保存在内存的高地址中,q种存储模式地址的高?sh)和数据位权有效地结合v来,高地址部分权值高Q低地址部分权gQ和我们的逻辑Ҏ(gu)一致?/span>

 

8bitC8bitchar16bitshort32bitlong 8163216bitshortx0x0010x0x11220x110x22大端模式Q就?/span>0x110x00100x220x0011X86KEIL C51ARMDSPARM二、D例说?/span>

AASCII650x4100 00 00 41 -----41 00 00 00  -----三、用代码判断大端模式

union/**

 * 得到当前pȝ的大端属?/span>, 32 */

static union {

       char c[4];

    unsigned long l;

}

 

endian_test = { { 'l', '?', '?', 'b' } }; #define ENDIANNESS ((char)endian_test.l)

 

/**

 * :  */

static union {

     short n;

     char c[sizeof(short)];

}un;

 

int getEndian()

{

   un.n = 0x0102;

 

   if ((un.c[0] == 1 && un.c[1] == 2))

   {

     printf("big endian/n");

   }

   else if ((un.c[0] == 2 && un.c[1] == 1))

   {

     printf("little endian/n");

   }

   else

     printf("error!/n");

 

   return 0;

}

 

/**

 * :  */

int getEndian()

{

   int c = 1;                               // big-endian: 00 00 00 01 little-endian: 01 00 00 00

  // int c = 0x02000001;          // big-endian: 02 00 00 01 little-endian: 01 00 00 02

 

   if ((*(char *)&c) == 1)               // c   {

     printf("little endian/n");

   }

   else

     printf("big endian");

 

   return 0;

}



]]>
【{】TCP三次握手/四次挥手详解 http://m.shnenglu.com/tianbianlan/archive/2012/01/11/164020.html天边?/dc:creator>天边?/author>Wed, 11 Jan 2012 15:49:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2012/01/11/164020.htmlhttp://m.shnenglu.com/tianbianlan/comments/164020.htmlhttp://m.shnenglu.com/tianbianlan/archive/2012/01/11/164020.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/164020.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/164020.htmlhttp://blog.csdn.net/sfwork/article/details/6876692
1、徏立连接协议(三次握手Q?wbr>
Q?Q客L(fng)发送一个带SYN标志的TCP报文到服务器。这是三ơ握手过E中的报??br />Q?Q?服务器端回应客户端的Q这是三ơ握手中的第2个报文,q个报文同时带ACK标志和SYN标志。因此它表示对刚才客L(fng)SYN报文的回应;同时又标志SYNl客L(fng)Q询问客L(fng)是否准备好进行数据通讯?br />Q?Q?客户必须再次回应服务D一个ACK报文Q这是报文段3?br />2、连接终止协议(四次挥手Q?wbr>
   ׃TCPq接是全双工的,因此每个方向都必d独进行关闭。这原则是当一方完成它的数据发送Q务后p发送一个FIN来终止这个方向的q接。收C?FIN只意味着q一方向上没有数据流动,一个TCPq接在收C个FIN后仍能发送数据。首先进行关闭的一方将执行d关闭Q而另一Ҏ(gu)行被动关闭?br /> Q?Q?TCP客户端发送一个FINQ用来关闭客户到服务器的数据传送(报文D?Q?br /> Q?Q?服务器收到这个FINQ它发回一个ACKQ确认序号ؓ(f)收到的序号加1Q报文段5Q。和SYN一P一个FIN占用一个序受?br /> Q?Q?服务器关闭客L(fng)的连接,发送一个FINl客L(fng)Q报文段6Q?br /> Q?Q?客户D发回ACK报文认Qƈ确认序可|ؓ(f)收到序号?Q报文段7Q?br />CLOSED: q个没什么好说的?jin),表示初始状态?br />LISTEN: q个也是非常Ҏ(gu)理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受q接?jin)?br />SYN_RCVD: q个状态表C接受到?jin)SYN报文Q在正常情况下,q个状态是服务器端的SOCKET在徏立TCPq接时的三次握手?x)话q程中的一个中间状态,很短暂,基本上用netstat你是很难看到q种状态的Q除非你Ҏ(gu)写了(jin)一个客L(fng)试E序Q故意将三次TCP握手q程中最后一个ACK报文不予发送。因此这U状态时Q当收到客户端的ACK报文后,它会(x)q入到ESTABLISHED状态?br />SYN_SENT: q个状态与SYN_RCVD遥想呼应Q当客户端SOCKET执行CONNECTq接Ӟ它首先发送SYN报文Q因此也随即它会(x)q入C(jin)SYN_SENT状态,q等待服务端的发送三ơ握手中的第2个报文。SYN_SENT状态表C客L(fng)已发送SYN报文?br />ESTABLISHEDQ这个容易理解了(jin)Q表C接已l徏立了(jin)?br />FIN_WAIT_1: q个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示{待Ҏ(gu)的FIN报文。而这两种状态的区别是:(x)FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时Q它想主动关闭连接,向对方发送了(jin)FIN报文Q此时该SOCKET卌入到FIN_WAIT_1状态。而当Ҏ(gu)回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论Ҏ(gu)何种情况下,都应该马上回应ACK报文Q所以FIN_WAIT_1状态一般是比较难见到的Q而FIN_WAIT_2状态还有时常常可以用netstat看到?br />FIN_WAIT_2Q上面已l详l解释了(jin)q种状态,实际上FIN_WAIT_2状态下的SOCKETQ表C半q接Q也x(chng)一方要求closeq接Q但另外q告诉对方,我暂时还有点数据需要传送给你,E后再关闭连接?br />TIME_WAIT: 表示收到?jin)对方的FIN报文Qƈ发送出?jin)ACK报文Q就{?MSL后即可回到CLOSED可用状态了(jin)。如果FIN_WAIT_1状态下Q收C(jin)Ҏ(gu)同时带FIN标志和ACK标志的报文时Q可以直接进入到TIME_WAIT状态,而无ȝqFIN_WAIT_2状态?br />CLOSING: q种状态比较特D,实际情况中应该是很少见,属于一U比较罕见的例外状态。正常情况下Q当你发送FIN报文后,按理来说是应该先收到Q或同时收到Q对方的ACK报文Q再收到Ҏ(gu)的FIN报文。但是CLOSING状态表CZ发送FIN报文后,q没有收到对方的ACK报文Q反而却也收C(jin)Ҏ(gu)的FIN报文。什么情况下?x)出现此U情况呢Q其实细想一下,也不隑־出结论:(x)那就是如果双方几乎在同时close一个SOCKET的话Q那么就出现?jin)双方同时发送FIN报文的情况,也即?x)出现CLOSING状态,表示双方都正在关闭SOCKETq接?br />CLOSE_WAIT: q种状态的含义其实是表C在{待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文l自己,你系l毫无疑问地?x)回应一个ACK报文l对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给Ҏ(gu)Q如果没有的话,那么你也可以closeq个SOCKETQ发送FIN报文l对方,也即关闭q接。所以你在CLOSE_WAIT状态下Q需要完成的事情是等待你d闭连接?br />LAST_ACK: q个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以q入到CLOSED可用状态了(jin)?br />最后有2个问题的回答Q我自己分析后的l论Q不一定保?00%正确Q?br />1?Z么徏立连接协议是三次握手Q而关闭连接却是四ơ握手呢Q?br />q是因ؓ(f)服务端的LISTEN状态下的SOCKET当收到SYN报文的徏q请求后Q它可以把ACK和SYNQACK起应{作用,而SYN起同步作用)(j)攑֜一个报文里来发送。但关闭q接Ӟ当收到对方的FIN报文通知Ӟ它仅仅表C对Ҏ(gu)有数据发送给你了(jin)Q但未必你所有的数据都全部发送给Ҏ(gu)?jin),所以你可以未必?x)马上?x)关闭SOCKET,也即你可能还需要发送一些数据给Ҏ(gu)之后Q再发送FIN报文l对Ҏ(gu)表示你同意现在可以关闭连接了(jin)Q所以它q里的ACK报文和FIN报文多数情况下都是分开发送的?br />2?Z么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
q是因ؓ(f)Q虽然双斚w同意关闭q接?jin),而且握手?个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(好比从SYN_SEND状态到ESTABLISH状态那P(j)Q但是因为我们必要假想|络是不可靠的,你无法保证你最后发送的ACK报文?x)一定被Ҏ(gu)收到Q因此对方处于LAST_ACK状态下的SOCKET可能?x)因时未收到ACK报文Q而重发FIN报文Q所以这个TIME_WAIT状态的作用是用来重发可能丢失的ACK报文?img src ="http://m.shnenglu.com/tianbianlan/aggbug/164020.html" width = "1" height = "1" />

]]>
B+数的实现--优秀代码http://m.shnenglu.com/tianbianlan/archive/2011/11/08/159814.html天边?/dc:creator>天边?/author>Tue, 08 Nov 2011 04:32:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2011/11/08/159814.htmlhttp://m.shnenglu.com/tianbianlan/comments/159814.htmlhttp://m.shnenglu.com/tianbianlan/archive/2011/11/08/159814.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/159814.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/159814.htmlhttp://idlebox.net/2007/stx-btree/


]]>
[转]C++ 对象的内存布局 http://m.shnenglu.com/tianbianlan/archive/2010/04/29/113987.html天边?/dc:creator>天边?/author>Thu, 29 Apr 2010 11:30:00 GMThttp://m.shnenglu.com/tianbianlan/archive/2010/04/29/113987.htmlhttp://m.shnenglu.com/tianbianlan/comments/113987.htmlhttp://m.shnenglu.com/tianbianlan/archive/2010/04/29/113987.html#Feedback0http://m.shnenglu.com/tianbianlan/comments/commentRss/113987.htmlhttp://m.shnenglu.com/tianbianlan/services/trackbacks/113987.html
2008-11-14 作者:(x)陈皓 来源Qcsdn


前言

07q?2月,我写?jin)一《C++虚函数表解析》的文章Q引起了(jin)大家的兴。有很多朋友Ҏ(gu)的文章留?jin)言Q有鼓励我的Q有批评我的Q还有很多问问题的。我在这里一q对大家的留a表示感谢。这也是我ؓ(f)什么再写一箋(hu)a的原因。因为,在上一文章中Q我用了(jin)的示例都是非常简单的Q主要是Z(jin)说明一些机理上的问题,也是Z(jin)图一些表达上方便和简单。不惻Iq篇文章成ؓ(f)?jin)打开C++对象模型内存布局的一个引子,引发?jin)大家对C++对象的更深层ơ的讨论。当?dng)我之前的文章q有很多斚w没有涉及(qing)Q从我个人感觉下来,在谈函数表里Q至有以下q些内容没有涉及(qing)Q?/p>

1Q有成员变量的情c(din)?/p>

2Q有重复l承的情c(din)?/p>

3Q有虚拟l承的情c(din)?/p>

4Q有ȝ型虚拟(h)承的情况?/p>

q些都是我本文章需要向大家说明的东ѝ所以,q篇文章会(x)是《C++虚函数表解析》的一个箋(hu),也是一高U进阶的文章。我希望大家在读q篇文章之前对C++有一定的基础和了(jin)解,q能先读我的上一文章。因文章的深度可能?x)比较深Q而且?x)比较杂乱,我希望你在读本篇文章时不会(x)有大脑思维紊ؕD大脑L的情c(din)?-)

对象的媄(jing)响因?/p>

而言之,我们一个类可能?x)有如下的?jing)响因素:(x)

1Q成员变?/p>

2Q虚函数Q生虚函数表)(j)

3Q单一l承Q只l承于一个类Q?/p>

4Q多重(h)承(l承多个c)(j)

5Q重复(h)承(l承的多个父cM其父cL相同的超c)(j)

6Q虚拟(h)承(使用virtual方式l承Qؓ(f)?jin)保证?h)承后父类的内存布局只会(x)存在一份)(j)

上述的东襉K常是C++q门语言在语义方面对对象内部的媄(jing)响因素,当然Q还?sh)(x)有~译器的影响Q比如优化)(j)Q还有字节对齐的影响。在q里我们都不讨论Q我们只讨论C++语言上的影响?/p>

本篇文章着重讨Zq几个情况下的C++对象的内存布局情况?/p>

1Q单一的一般(h)承(带成员变量、虚函数、虚函数覆盖Q?/p>

2Q单一的虚拟(h)承(带成员变量、虚函数、虚函数覆盖Q?/p>

3Q多重(h)承(带成员变量、虚函数、虚函数覆盖Q?/p>

4Q重复多重(h)承(带成员变量、虚函数、虚函数覆盖Q?/p>

5Q钻矛_的虚拟多重(h)承(带成员变量、虚函数、虚函数覆盖Q?/p>

我们的目标就是,让事情越来越复杂?/p>

知识复习(fn)

我们单地复习(fn)一下,我们可以通过对象的地址来取得虚函数表的地址Q如Q?/p>

typedef void(*Fun)(void);

Base b;

Fun pFun = NULL;

cout << "虚函数表地址Q? << (int*)(&b) << endl;

cout << "虚函数表 ?W一个函数地址Q? << (int*)*(int*)(&b) << endl;

// Invoke the first virtual function

pFun = (Fun)*((int*)*(int*)(&b));

pFun();

我们同样可以用这U方式来取得整个对象实例的内存布局。因些东西在内存?sh)都是连l分布的Q我们只需要用适当的地址偏移量,我们可以获得整个内存对象的布局?/p>

本篇文章中的例程或内存布局主要使用如下~译器和pȝQ?/p>

1QWindows XP ?VC++ 2003

2QCygwin ?G++ 3.4.4

单一的一般(h)?/strong>

下面Q我们假设有如下所C的一个(h)承关p:(x)

h意,在这个(h)承关pMQ父c,子类Q孙子类都有自己的一个成员变量。而了(jin)c覆盖了(jin)父类的f()Ҏ(gu)Q孙子类覆盖?jin)子cȝg_child()?qing)其类的f()?/p>

我们的源E序如下所C:(x)

class Parent {

public:

int iparent;

Parent ():iparent (10) {}

virtual void f() { cout << " Parent::f()" << endl; }

virtual void g() { cout << " Parent::g()" << endl; }

virtual void h() { cout << " Parent::h()" << endl; }

 

};

 

class Child : public Parent {

public:

int ichild;

Child():ichild(100) {}

virtual void f() { cout << "Child::f()" << endl; }

virtual void g_child() { cout << "Child::g_child()" << endl; }

virtual void h_child() { cout << "Child::h_child()" << endl; }

};

 

class GrandChild : public Child{

public:

int igrandchild;

GrandChild():igrandchild(1000) {}

virtual void f() { cout << "GrandChild::f()" << endl; }

virtual void g_child() { cout << "GrandChild::g_child()" << endl; }

virtual void h_grandchild() { cout << "GrandChild::h_grandchild()" << endl; }

};

我们使用以下E序作ؓ(f)试E序Q(下面E序中,我用了(jin)一个int** pVtab 来作为遍历对象内存布局的指针,q样Q我可以方便地像用数l一h遍历所有的成员包括其虚函数表了(jin)Q在后面的程序中Q我也是用这L(fng)Ҏ(gu)的,请不必感到奇怪,Q?/p>

typedef void(*Fun)(void);

GrandChild gc;

int** pVtab = (int**)&gc;

cout << "[0] GrandChild::_vptr->" << endl;

for (int i=0; (Fun)pVtab[0][i]!=NULL; i++){

pFun = (Fun)pVtab[0][i];

cout << " ["<<i<<"] ";

pFun();

}

cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;

cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;

cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;

其运行结果如下所C:(x)Q在VC++ 2003和G++ 3.4.4下)(j)

[0] GrandChild::_vptr->

    [0] GrandChild::f()

    [1] Parent::g()

    [2] Parent::h()

    [3] GrandChild::g_child()

    [4] Child::h1()

    [5] GrandChild::h_grandchild()

[1] Parent.iparent = 10

[2] Child.ichild = 100

[3] GrandChild.igrandchild = 1000

使用囄表示如下Q?/p>

可见以下几个斚wQ?/p>

1Q虚函数表在最前面的位|?/p>

2Q成员变量根据其l承和声明顺序依ơ放在后面?/p>

3Q在单一的(h)承中Q被overwrite的虚函数在虚函数表中得到?jin)更新?/p>

多重l承

下面Q再让我们来看看多重l承中的情况Q假设有下面q样一个类的(h)承关pR注意:(x)子类只overwrite?jin)父cȝf()函数Q而还有一个是自己的函敎ͼ我们q样做的目的是ؓ(f)?jin)用g1()作ؓ(f)一个标记来标明子类的虚函数表)(j)。而且每个cM都有一个自q成员变量Q?/p>

我们的类l承的源代码如下所C:(x)父类的成员初始ؓ(f)10Q?0Q?0Q子cȝ?00

class Base1 {

public:

int ibase1;

Base1():ibase1(10) {}

virtual void f() { cout << "Base1::f()" << endl; }

virtual void g() { cout << "Base1::g()" << endl; }

virtual void h() { cout << "Base1::h()" << endl; }

 

};

class Base2 {

public:

int ibase2;

Base2():ibase2(20) {}

virtual void f() { cout << "Base2::f()" << endl; }

virtual void g() { cout << "Base2::g()" << endl; }

virtual void h() { cout << "Base2::h()" << endl; }

};

class Base3 {

public:

int ibase3;

Base3():ibase3(30) {}

virtual void f() { cout << "Base3::f()" << endl; }

virtual void g() { cout << "Base3::g()" << endl; }

virtual void h() { cout << "Base3::h()" << endl; }

};

class Derive : public Base1, public Base2, public Base3 {

public:

int iderive;

Derive():iderive(100) {}

virtual void f() { cout << "Derive::f()" << endl; }

virtual void g1() { cout << "Derive::g1()" << endl; }

};

我们通过下面的程序来查看子类实例的内存布局Q下面程序中Q注意我使用?jin)一个s变量Q其中用C(jin)sizof(Base)来找下一个类的偏U量。(因ؓ(f)我声明的是int成员Q所以是4个字节,所以没有对齐问题。关于内存的寚w问题Q大家可以自行试验,我在q里׃多说?jin)?j)

typedef void(*Fun)(void);

Derive d;

int** pVtab = (int**)&d;

cout << "[0] Base1::_vptr->" << endl;

pFun = (Fun)pVtab[0][0];

cout << " [0] ";

pFun();

pFun = (Fun)pVtab[0][1];

cout << " [1] ";pFun();

pFun = (Fun)pVtab[0][2];

cout << " [2] ";pFun();

pFun = (Fun)pVtab[0][3];

cout << " [3] "; pFun();

pFun = (Fun)pVtab[0][4];

cout << " [4] "; cout<<pFun<<endl;

cout << "[1] Base1.ibase1 = " << (int)pVtab[1] << endl;

int s = sizeof(Base1)/4;

cout << "[" << s << "] Base2::_vptr->"<<endl;

pFun = (Fun)pVtab[s][0];

cout << " [0] "; pFun();

Fun = (Fun)pVtab[s][1];

cout << " [1] "; pFun();

pFun = (Fun)pVtab[s][2];

cout << " [2] "; pFun();

pFun = (Fun)pVtab[s][3];

out << " [3] ";

cout<<pFun<<endl;

cout << "["<< s+1 <<"] Base2.ibase2 = " << (int)pVtab[s+1] << endl;

s = s + sizeof(Base2)/4;

cout << "[" << s << "] Base3::_vptr->"<<endl;

pFun = (Fun)pVtab[s][0];

cout << " [0] "; pFun();

 

pFun = (Fun)pVtab[s][1];

cout << " [1] "; pFun();

pFun = (Fun)pVtab[s][2];

cout << " [2] "; pFun();

 

pFun = (Fun)pVtab[s][3];

cout << " [3] ";

cout<<pFun<<endl;

s++;

cout << "["<< s <<"] Base3.ibase3 = " << (int)pVtab[s] << endl;

s++;

cout << "["<< s <<"] Derive.iderive = " << (int)pVtab[s] << endl;

其运行结果如下所C:(x)Q在VC++ 2003和G++ 3.4.4下)(j)

[0] Base1::_vptr->

     [0] Derive::f()

     [1] Base1::g()

     [2] Base1::h()

     [3] Driver::g1()

     [4] 00000000      ç 注意Q在GCC下,q里?/span>1

[1] Base1.ibase1 = 10

[2] Base2::_vptr->

     [0] Derive::f()

     [1] Base2::g()

     [2] Base2::h()

     [3] 00000000      ç 注意Q在GCC下,q里?/span>1

[3] Base2.ibase2 = 20

[4] Base3::_vptr->

     [0] Derive::f()

     [1] Base3::g()

     [2] Base3::h()

     [3] 00000000

[5] Base3.ibase3 = 30

[6] Derive.iderive = 100

使用囄表示是下面这个样子:(x)

我们可以看到Q?/p>

1Q?每个父类都有自己的虚表?/p>

2Q?子类的成员函数被攑ֈ?jin)第一个父cȝ表中?/p>

3Q?内存布局中,其父cd局依次按声明顺序排列?/p>

4Q?每个父类的虚表中的f()函数都被overwrite成了(jin)子类的f()。这样做是Z(jin)解决不同的父cȝ型的指针指向同一个子cd例,而能够调用到实际的函数?/p>

重复l承

下面我们再来看看Q发生重复(h)承的情况。所谓重复(h)承,也就是某个基c被间接地重复(h)承了(jin)多次?/p>

下图是一个(h)承图Q我们重载了(jin)父类的f()函数?/p>

其类l承的源代码如下所C。其中,每个c都有两个变量,一个是整ŞQ?字节Q,一个是字符Q?字节Q,而且q有自己的虚函数Q自己overwrite父类的虚函数。如子类D中,f()覆盖?jin)超cȝ函数Q?f1() 和f2() 覆盖?jin)其父类的虚函数QDf()q虚函数?/p>

class B

{

public:

int ib;

char cb;

public:

B():ib(0),cb('B') {}

virtual void f() { cout << "B::f()" << endl;}

virtual void Bf() { cout << "B::Bf()" << endl;}

};

class B1 : public B

{

public:

int ib1;

char cb1;

public:

B1():ib1(11),cb1('1') {}

virtual void f() { cout << "B1::f()" << endl;}

virtual void f1() { cout << "B1::f1()" << endl;}

virtual void Bf1() { cout << "B1::Bf1()" << endl;}

};

class B2: public B

{

public:

int ib2;

char cb2;

public:

B2():ib2(12),cb2('2') {}

virtual void f() { cout << "B2::f()" << endl;}

virtual void f2() { cout << "B2::f2()" << endl;}

virtual void Bf2() { cout << "B2::Bf2()" << endl;}

};

class D : public B1, public B2

{

public:

int id;

char cd;

public:

D():id(100),cd('D') {}

virtual void f() { cout << "D::f()" << endl;}

virtual void f1() { cout << "D::f1()" << endl;}

virtual void f2() { cout << "D::f2()" << endl;}

virtual void Df() { cout << "D::Df()" << endl;}

};

我们用来存取子类内存布局的代码如下所C:(x)Q在VC++ 2003和G++ 3.4.4下)(j)

typedef void(*Fun)(void);

int** pVtab = NULL;

Fun pFun = NULL;

D d;

pVtab = (int**)&d;

cout << "[0] D::B1::_vptr->" << endl;

pFun = (Fun)pVtab[0][0];

cout << " [0] "; pFun();

pFun = (Fun)pVtab[0][1];

cout << " [1] "; pFun();

pFun = (Fun)pVtab[0][2];

cout << " [2] "; pFun();

pFun = (Fun)pVtab[0][3];

cout << " [3] "; pFun();

pFun = (Fun)pVtab[0][4];

cout << " [4] "; pFun();

pFun = (Fun)pVtab[0][5];

cout << " [5] 0x" << pFun << endl;

cout << "[1] B::ib = " << (int)pVtab[1] << endl;

cout << "[2] B::cb = " << (char)pVtab[2] << endl;

cout << "[3] B1::ib1 = " << (int)pVtab[3] << endl;

cout << "[4] B1::cb1 = " << (char)pVtab[4] << endl;

cout << "[5] D::B2::_vptr->" << endl;

pFun = (Fun)pVtab[5][0];

cout << " [0] "; pFun();

pFun = (Fun)pVtab[5][1];

cout << " [1] "; pFun();

pFun = (Fun)pVtab[5][2];

cout << " [2] "; pFun();

pFun = (Fun)pVtab[5][3];

cout << " [3] "; pFun();

pFun = (Fun)pVtab[5][4];

cout << " [4] 0x" << pFun << endl;

cout << "[6] B::ib = " << (int)pVtab[6] << endl;

cout << "[7] B::cb = " << (char)pVtab[7] << endl;

cout << "[8] B2::ib2 = " << (int)pVtab[8] << endl;

cout << "[9] B2::cb2 = " << (char)pVtab[9] << endl;

cout << "[10] D::id = " << (int)pVtab[10] << endl;

cout << "[11] D::cd = " << (char)pVtab[11] << endl;

E序q行l果如下Q?/p>

GCC 3.4.4

VC++ 2003

[0] D::B1::_vptr->

     [0] D::f()

     [1] B::Bf()

     [2] D::f1()

     [3] B1::Bf1()

     [4] D::f2()

     [5] 0x1

[1] B::ib = 0

[2] B::cb = B

[3] B1::ib1 = 11

[4] B1::cb1 = 1

[5] D::B2::_vptr->

     [0] D::f()

     [1] B::Bf()

     [2] D::f2()

     [3] B2::Bf2()

     [4] 0x0

[6] B::ib = 0

[7] B::cb = B

[8] B2::ib2 = 12

[9] B2::cb2 = 2

[10] D::id = 100

[11] D::cd = D

[0] D::B1::_vptr->

     [0] D::f()

     [1] B::Bf()

     [2] D::f1()

     [3] B1::Bf1()

     [4] D::Df()

     [5] 0x00000000

[1] B::ib = 0

[2] B::cb = B

[3] B1::ib1 = 11

[4] B1::cb1 = 1

[5] D::B2::_vptr->

     [0] D::f()

     [1] B::Bf()

     [2] D::f2()

     [3] B2::Bf2()

     [4] 0x00000000

[6] B::ib = 0

[7] B::cb = B

[8] B2::ib2 = 12

[9] B2::cb2 = 2

[10] D::id = 100

[11] D::cd = D

下面是对于子cd例中的虚函数表的图:(x)

我们可以看见Q最端的父cB其成员变量存在于B1和B2中,q被Dl(h)承下M(jin)。而在D中,其有B1和B2的实例,于是B的成员在D的实例中存在两䆾Q一份是B1l承而来的,另一份是B2l承而来的。所以,如果我们使用以下语句Q则?x)生二义性编译错误:(x)

D d;

d.ib = 0; //二义性错?/p>

d.B1::ib = 1; //正确

d.B2::ib = 2; //正确

注意Q上面例E中的最后两条语句存取的是两个变量。虽然我们消除了(jin)二义性的~译错误Q但BcdD中还是有两个实例Q这U(h)扉K成?jin)数据的重复Q我们叫q种l承为重复(h)ѝ重复的基类数据成员可能q不是我们想要的。所以,C++引入?jin)虚基类的概c(din)?/p>

ȝ型多重虚拟(h)?/strong>

虚拟l承的出现就是ؓ(f)?jin)解决重复?h)承中多个间接父类的问题的。钻矛_的结构是其最l典的结构。也是我们在q里要讨论的l构Q?/p>

上述?#8220;重复l承”只需要把B1和B2l承B的语法中加上virtual 关键Q就成了(jin)虚拟l承Q其l承囑֦下所C:(x)

上图和前面的“重复l承”中的cȝ内部数据和接口都是完全一L(fng)Q只是我们采用了(jin)虚拟l承Q其省略后的源码如下所C:(x)

class B {……};

class B1 : virtual public B{……};

class B2: virtual public B{……};

class D : public B1, public B2{ …… };

在查看D之前Q我们先看一看单一虚拟l承的情c(din)下面是一D在VC++2003下的试E序Q(因ؓ(f)VC++和GCC的内存而局上有一些细节上的不同,所以这里只l出VC++的程序,GCC下的E序大家可以Ҏ(gu)我给出的E序自己仿照着写一个去试一试)(j)Q?/p>

int** pVtab = NULL;

Fun pFun = NULL;

 

B1 bb1;

pVtab = (int**)&bb1;

cout << "[0] B1::_vptr->" << endl;

pFun = (Fun)pVtab[0][0];

cout << " [0] ";

pFun(); //B1::f1();

cout << " [1] ";

pFun = (Fun)pVtab[0][1];

pFun(); //B1::bf1();

cout << " [2] ";

cout << pVtab[0][2] << endl;

cout << "[1] = 0x";

cout << (int*)*((int*)(&bb1)+1) <<endl; //B1::ib1

cout << "[2] B1::ib1 = ";

cout << (int)*((int*)(&bb1)+2) <<endl; //B1::ib1

cout << "[3] B1::cb1 = ";

cout << (char)*((int*)(&bb1)+3) << endl; //B1::cb1

cout << "[4] = 0x";

cout << (int*)*((int*)(&bb1)+4) << endl; //NULL

cout << "[5] B::_vptr->" << endl;

pFun = (Fun)pVtab[5][0];

cout << " [0] ";

pFun(); //B1::f();

pFun = (Fun)pVtab[5][1];

cout << " [1] ";

pFun(); //B::Bf();

cout << " [2] ";

cout << "0x" << (Fun)pVtab[5][2] << endl;

cout << "[6] B::ib = ";

cout << (int)*((int*)(&bb1)+6) <<endl; //B::ib

cout << "[7] B::cb = ";

其运行结果如下(我结Z(jin)GCC的和VC++2003的对比)(j)Q?/p>

GCC 3.4.4

VC++ 2003

[0] B1::_vptr ->

    [0] : B1::f()

    [1] : B1::f1()

    [2] : B1::Bf1()

    [3] : 0

[1] B1::ib1 : 11

[2] B1::cb1 : 1

[3] B::_vptr ->

    [0] : B1::f()

    [1] : B::Bf()

    [2] : 0

[4] B::ib : 0

[5] B::cb : B

[6] NULL : 0

[0] B1::_vptr->

     [0] B1::f1()

     [1] B1::Bf1()

     [2] 0

[1] = 0x00454310 ç该地址取值后?/span>-4

[2] B1::ib1 = 11

[3] B1::cb1 = 1

[4] = 0x00000000

[5] B::_vptr->

     [0] B1::f()

     [1] B::Bf()

     [2] 0x00000000

[6] B::ib = 0

[7] B::cb = B

q里Q大家可以自己对比一下。关于细节上Q我?x)在后面一q再说?/p>

下面的测试程序是看子cD的内存布局Q同hVC++ 2003的(因ؓ(f)VC++和GCC的内存布局上有一些细节上的不同,而VC++的相对要清楚很多Q所以这里只l出VC++的程序,GCC下的E序大家可以Ҏ(gu)我给出的E序自己仿照着写一个去试一试)(j)Q?/p>

D d;

pVtab = (int**)&d;

cout << "[0] D::B1::_vptr->" << endl;

pFun = (Fun)pVtab[0][0];

cout << " [0] "; pFun(); //D::f1();

pFun = (Fun)pVtab[0][1];

cout << " [1] "; pFun(); //B1::Bf1();

pFun = (Fun)pVtab[0][2];

cout << " [2] "; pFun(); //D::Df();

pFun = (Fun)pVtab[0][3];

cout << " [3] ";

cout << pFun << endl;

//cout << pVtab[4][2] << endl;

cout << "[1] = 0x";

cout << (int*)((&dd)+1) <<endl; //????

cout << "[2] B1::ib1 = ";

cout << *((int*)(&dd)+2) <<endl; //B1::ib1

cout << "[3] B1::cb1 = ";

cout << (char)*((int*)(&dd)+3) << endl; //B1::cb1

//---------------------

cout << "[4] D::B2::_vptr->" << endl;

pFun = (Fun)pVtab[4][0];

cout << " [0] "; pFun(); //D::f2();

pFun = (Fun)pVtab[4][1];

cout << " [1] "; pFun(); //B2::Bf2();

pFun = (Fun)pVtab[4][2];

cout << " [2] ";

cout << pFun << endl;

cout << "[5] = 0x";

cout << *((int*)(&dd)+5) << endl; // ???

cout << "[6] B2::ib2 = ";

cout << (int)*((int*)(&dd)+6) <<endl; //B2::ib2

cout << "[7] B2::cb2 = ";

cout << (char)*((int*)(&dd)+7) << endl; //B2::cb2

cout << "[8] D::id = ";

cout << *((int*)(&dd)+8) << endl; //D::id

cout << "[9] D::cd = ";

cout << (char)*((int*)(&dd)+9) << endl;//D::cd

cout << "[10] = 0x";

cout << (int*)*((int*)(&dd)+10) << endl;

//---------------------

cout << "[11] D::B::_vptr->" << endl;

pFun = (Fun)pVtab[11][0];

cout << " [0] "; pFun(); //D::f();

pFun = (Fun)pVtab[11][1];

cout << " [1] "; pFun(); //B::Bf();

pFun = (Fun)pVtab[11][2];

cout << " [2] ";

cout << pFun << endl;

cout << "[12] B::ib = ";

cout << *((int*)(&dd)+12) << endl; //B::ib

cout << "[13] B::cb = ";

cout << (char)*((int*)(&dd)+13) <<endl;//B::cb

下面l出q行后的l果Q分VC++和GCC两部份)(j)

GCC 3.4.4

VC++ 2003

[0] B1::_vptr ->

    [0] : D::f()

    [1] : D::f1()

    [2] : B1::Bf1()

    [3] : D::f2()

    [4] : D::Df()

    [5] : 1

[1] B1::ib1 : 11

[2] B1::cb1 : 1

[3] B2::_vptr ->

    [0] : D::f()

    [1] : D::f2()

    [2] : B2::Bf2()

    [3] : 0

[4] B2::ib2 : 12

[5] B2::cb2 : 2

[6] D::id : 100

[7] D::cd : D

[8] B::_vptr ->

    [0] : D::f()

    [1] : B::Bf()

    [2] : 0

[9] B::ib : 0

[10] B::cb : B

[11] NULL : 0

[0] D::B1::_vptr->

     [0] D::f1()

     [1] B1::Bf1()

     [2] D::Df()

     [3] 00000000

[1] = 0x0013FDC4  ç 该地址取值后?/span>-4

[2] B1::ib1 = 11

[3] B1::cb1 = 1

[4] D::B2::_vptr->

     [0] D::f2()

     [1] B2::Bf2()

     [2] 00000000

[5] = 0x4539260   ç 该地址取值后?/span>-4

[6] B2::ib2 = 12

[7] B2::cb2 = 2

[8] D::id = 100

[9] D::cd = D

[10]  = 0x00000000

[11] D::B::_vptr->

     [0] D::f()

     [1] B::Bf()

     [2] 00000000

[12] B::ib = 0

[13] B::cb = B

关于虚拟l承的运行结果我׃d?jin)(前面的作囑ַl让我生了(jin)很严重的厌倦感Q所以就偷个懒了(jin)Q大家见谅了(jin)Q?/p>

在上面的输出l果中,我用不同的颜色做?jin)一些标明。我们可以看到如下的几点Q?/p>

1Q无论是GCCq是VC++Q除?jin)一些细节上的不同,其大体上的对象布局是一L(fng)。也是_(d)先是B1Q黄Ԍ(j)Q然后是B2Q绿Ԍ(j)Q接着是DQ灰Ԍ(j)Q而Bq个类Q青蓝色Q的实例都放在最后的位置?/p>

2Q关于虚函数表,其是第一个虚表,GCC和VC++有很重大的不一栗但仔细看下来,q是VC++的虚表比较清晰和有逻辑性?/p>

3QVC++和GCC都把Bq个类攑ֈ?jin)最后,而VC++有一个NULL分隔W把B和B1和B2的布局分开。GCC则没有?/p>

4QVC++中的内存布局有两个地址我有些不是很明白Q在其中我用U色标出?jin)。取其内Ҏ(gu)-4。接道理来说Q这个指针应该是指向B(ti)cd例的内存地址Q这个做法就是ؓ(f)?jin)保证重复的父类只有一个实例的技术)(j)。但取值后却不是。这Ҏ(gu)目前qƈ不太清楚Q还向大家请教?/p>

5QGCC的内存布局中在B1和B2中则没有指向B(ti)的指针。这点可以理解,~译器可以通过计算B1和B2的size而得出B的偏U量?/p>

l束?/strong>

C++q门语言是一门比较复杂的语言Q对于程序员来说Q我们似乎永q摸不清楚这门语a背着我们在干?jin)什么。需要熟(zhn)这门语aQ我们就必需要了(jin)解C++里面的那些东西,需要我们去?jin)解他后面的内存对象。这h们才能真正的?jin)解C++Q从而能够更好的使用C++q门最隄~程语言?/p>

在文章束之前q是介绍一下自己吧。我从事软g研发有十个年头了(jin)Q目前是软g开发技术主,技术方面,LUnix/C/C++Q比较喜Ƣ网l上的技术,比如分布式计,|格计算QP2PQAjax{一切和互联|相关的东西。管理方面比较擅长于团队Q技术趋势分析,目理。欢q大家和我交,我的MSN和Email是:(x)haoel@hotmail.com



]]>
Boost.Regex库学?fn)笔?/title><link>http://m.shnenglu.com/tianbianlan/archive/2009/07/24/91015.html</link><dc:creator>天边?/dc:creator><author>天边?/author><pubDate>Fri, 24 Jul 2009 03:48:00 GMT</pubDate><guid>http://m.shnenglu.com/tianbianlan/archive/2009/07/24/91015.html</guid><wfw:comment>http://m.shnenglu.com/tianbianlan/comments/91015.html</wfw:comment><comments>http://m.shnenglu.com/tianbianlan/archive/2009/07/24/91015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/tianbianlan/comments/commentRss/91015.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/tianbianlan/services/trackbacks/91015.html</trackback:ping><description><![CDATA[     摘要:   在C++~程中,有一点让人挺遗憾的就是C++不支持正则表达式,q让很多用户Z(jin)~写支持正则表达式程序而不得不攑ּC++。然而,Boost.Regex库填补了(jin)C++在这斚w的空白,它C++很好的支持各U引擎的正则表达式?       l合我的学习(fn)Q逐步分析Boost.Regex库?  &nbs...  <a href='http://m.shnenglu.com/tianbianlan/archive/2009/07/24/91015.html'>阅读全文</a><img src ="http://m.shnenglu.com/tianbianlan/aggbug/91015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/tianbianlan/" target="_blank">天边?/a> 2009-07-24 11:48 <a href="http://m.shnenglu.com/tianbianlan/archive/2009/07/24/91015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.1118.org.cn" target="_blank">ŷþ޾Ʒ</a>| <a href="http://www.jxlbw.cn" target="_blank">㽶99þùۺϾƷլ</a>| <a href="http://www.650qq.cn" target="_blank">Ʒþþþþ</a>| <a href="http://www.dfpt.net.cn" target="_blank">ĻþþƷ1 </a>| <a href="http://www.awo6.cn" target="_blank">þùAVJUST鶹</a>| <a href="http://www.qkqkkq.cn" target="_blank">һɫþۺϺݺƪ</a>| <a href="http://www.miror.com.cn" target="_blank">պŷ޹ƷĻþþ</a>| <a href="http://www.jrlxcc.cn" target="_blank">AV˾þԭ</a>| <a href="http://www.shoescaps.cn" target="_blank">Ʒþþ㽶</a>| <a href="http://www.idhm.cn" target="_blank">޾ƷþþþþͼƬ </a>| <a href="http://www.hxjxjt88.cn" target="_blank">þþþavרˮ</a>| <a href="http://www.kuruishanghai.cn" target="_blank">þþƷëƬѹۿ</a>| <a href="http://www.weipengdq.cn" target="_blank">99Ʒþ</a>| <a href="http://www.lockdealing.cn" target="_blank">һƷþ</a>| <a href="http://www.zzjiale.cn" target="_blank">޾Ʒһþ</a>| <a href="http://www.1314liao.cn" target="_blank">޾Ʒһ߾þ</a>| <a href="http://www.www9785.cn" target="_blank">99þó˹Ʒ </a>| <a href="http://www.jxjkyt.cn" target="_blank">þþƷ˳</a>| <a href="http://www.caribbeanlagoon.com.cn " target="_blank">һþþþþþ</a>| <a href="http://www.huaigutang.cn" target="_blank">ۺһ˾þþƷ</a>| <a href="http://www.kong-ya-ji-wang.com.cn" target="_blank">þĻ˿</a>| <a href="http://www.node-js.cn" target="_blank">99鶹þþùƷ</a>| <a href="http://www.liess.cn" target="_blank">ҹƷþþþþžŵӰ </a>| <a href="http://www.awhahzm.cn" target="_blank">þ99Ʒ鶹</a>| <a href="http://www.sifaguojinb.cn" target="_blank">þ㽶Ƶ</a>| <a href="http://www.dszixun.cn" target="_blank">Ļþ</a>| <a href="http://www.gkdb.net.cn" target="_blank">þþƷһ</a>| <a href="http://www.wps2009.cn" target="_blank">ɫۺϾþۺۿ</a>| <a href="http://www.zhougong.net.cn" target="_blank">&#228;v뾫Ʒþþ</a>| <a href="http://www.dripnews.cn" target="_blank">Ʒþþþ</a>| <a href="http://www.gaokaocaiti.cn" target="_blank">99reþþƷҳ2020</a>| <a href="http://www.91share.com.cn" target="_blank">þþƷƷëƬ</a>| <a href="http://www.gongnian.cn" target="_blank">þˬˬav </a>| <a href="http://www.sdhaomai.cn" target="_blank">þĻԴվ</a>| <a href="http://www.inqh.cn" target="_blank">鶹AV뾫Ʒþ</a>| <a href="http://www.senbozulin.com.cn" target="_blank">Ů㽶þ**ëƬƷ</a>| <a href="http://www.x4565.cn" target="_blank">޹㽶ˬAVƬþ</a>| <a href="http://www.yjtrade.cn" target="_blank">ƷѾþþþþþ</a>| <a href="http://www.jjygw.cn" target="_blank">޾Ʒ97þĻ</a>| <a href="http://www.024cg.cn" target="_blank">97þþƷһ</a>| <a href="http://www.fridc.cn" target="_blank">ҹƷþþþþþ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>