2* b2ptr=&d; printf("b2ptr\t%p\n", b2ptr); void* ptr2=b2ptr->vfun(); printf("ptr2\t%p\n", ptr2); } : " " D::vfun(), :
dptr    0012FF6C
D::vfun(): this=0012FF6C
ptr1    0012FF6C
b2ptr   0012FF70
D::vfun(): this=0012FF6C
ptr2    0012FF70
.. D::vfun(), (ptr1!=ptr2), , , .

, 361 "12.2.6. ", this this . , , vtbl . -, vtbl:

// 

//  D::vfun,  
D* D::vfun(D *const this)
{
 // ...
}

//   -   D::vfun() 
//     B2
B2* D::vfun_stub(B2 *const this)
{
 return D::vfun(this+delta_1)+delta_2;
}
delta_2, , delta_1.

, , " ". , , :

10.3. [class.virtual]

  1. (covariant). D::f B::f, , : D::f B::f, D::f D::f D. ( ), () (5.2.2). :
    class B {};
    class D : private B { friend class Derived; };
    struct Base {
     virtual void vf1();
     virtual void vf2();
     virtual void vf3();
     virtual B*   vf4();
     virtual B*   vf5();
     void f();
    };
    
    struct No_good : public Base {
     D* vf4();  // : B (  D) 
    };
    
    class A;
    struct Derived : public Base {
     void vf1();     //    Base::vf1()
     void vf2(int);  //  ,  Base::vf2()
     char vf3();     // :    
     D*   vf4();     // OK:     
     A*   vf5();     // :     
     void f();
    };
    
    void g()
    {
     Derived d;
     Base* bp=&d;      //  : Derived*  Base*
     bp->vf1();        //   Derived::vf1()
     bp->vf2();        //   Base::vf2()
     bp->f();          //   Base::f()  ( )
     B* p=bp->vf4();   //   Derived::pf()  
                       //   B*
     Derived* dp=&d;
     D* q=dp->vf4();   //   Derived::pf(), 
                       //   B*  
     dp->vf2();        // :  
    }
" cv-"?

3.9.3. CV- [basic.type.qualifier]

  1. cv- :

    cv- < const
    cv- < volatile
    cv- < const volatile
    const < const volatile
    volatile < const volatile


.498: 16.2.3. STL-

.

, , STL . , , , ? , , , () . STL , ?

:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <list>

struct List {  //  
       struct Data {
              int val;
              Data* next;

              Data(int v, Data* n=0) : val(v), next(n) {}
       };

       Data *head, *tail;

       List() { head=tail=0; }

       ~List()
       {
        for (Data *ptr=head, *n; ptr; ptr=n) {  //   
            n=ptr->next;
            delete ptr;
        }
       }

       void push_back(int v)  //  
       {
        if (!head) head=tail=new Data(v);
        else tail=tail->next=new Data(v);
       }
};

long Count, Var;

void f1()
{
 List lst;
 for (int i=0; i<1000; i++)
     lst.push_back(i);

 for (List::Data* ptr=lst.head; ptr; ptr=ptr->next)
     Var+=ptr->val;
}

void f2()
{
 typedef std::list<int> list_type;

 list_type lst;
 for (int i=0; i<1000; i++)
     lst.push_back(i);

 for (list_type::const_iterator ci=lst.begin(), cend=lst.end(); ci!=cend; ++ci)
     Var+=*ci;
}

int main(int argc, char** argv)
{
 if (argc>1) Count=atol(argv[1]);

 clock_t c1,c2;
 {
  c1=clock();

  for (long i=0; i<Count; i++)
      for (long j=0; j<1000; j++)
          f1();

  c2=clock();
  printf("f1(): %ld ths calls per %.1f sec\n", Count, double(c2-c1)/CLK_TCK);
 }
 {
  c1=clock();

  for (long i=0; i<Count; i++)
      for (long j=0; j<1000; j++)
          f2();

  c2=clock();
  printf("f2(): %ld ths calls per %.1f sec\n", Count, double(c2-c1)/CLK_TCK);
 }
}
f1() List: 1000 , .

.. STL ( , ), :

struct List {  //  
       struct Data {

              // ...

              //    
              static Data* free;
              static void allocate();
              void* operator new(size_t);
              void operator delete(void*, size_t);
       };

       // ...

};

List::Data* List::Data::free;

void List::Data::allocate()
{
 const int sz=100;  //    sz 
 free=reinterpret_cast<Data*>(new char[sz*sizeof(Data)]);

 //   
 for (int i=0; i<sz-1; i++)
     free[i].next=free+i+1;
 free[sz-1].next=0;
}

inline void* List::Data::operator new(size_t)
{
 if (!free) allocate();

 Data* ptr=free;
 free=free->next;

 return ptr;
}

inline void List::Data::operator delete(void* dl, size_t)
{  //      
 Data* ptr=static_cast<Data*>(dl);
 ptr->next=free;
 free=ptr;
}
, . memory leak ( ) -- memory pool, .. . , memory leak memory pool , : , , , , .

, -- (NULL-). , , ..:

inline void List::Data::operator delete(void* dl, size_t)
{
 if (!dl) return;  //  NULL

 //      
 Data* ptr=static_cast<Data*>(dl);
 ptr->next=free;
 free=ptr;
}
, , -- std::list<int>:
struct DList {  //  
       struct Data {
              int val;
              Data *prev, *next;

              Data(int v, Data* p=0, Data* n=0) : val(v), prev(p), next(n) {}

              //    
              static Data* free;
              static void allocate();
              void* operator new(size_t);
              void operator delete(void*, size_t);
       };

       Data *head, *tail;

       DList() { head=tail=0; }

       ~DList()
       {
        for (Data *ptr=head, *n; ptr; ptr=n) {  //   
            n=ptr->next;
            delete ptr;
        }
       }

       void push_back(int v)  //  
       {
        if (!head) head=tail=new Data(v);
        else tail=tail->next=new Data(v, tail);
       }
};
, , . , :

 

f1() f2() f1() f2() f1() f2()
1 9.6 12.1 1.1 12.1 1.3 12.1
2 20.2 2.5 1.8 2.5 1.9 2.5

?

, , STL . , , STL .

.505: 16.3.4.

10 000 vr Record(), s1 vi int().

10 000 -- . 10 000 , , :

vector<X> vx;          //   
vx.reserve(10000);     //    ""
                       //   push_back()
// ...
vx.push_back(x_work);  //     
, .. STL 3.2 sgi
vector<int> vi(s1);
:
for (int i=0; i<s1; i++)
    vi.elements[i]=0;
memset():
memset(vi.elements, 0, sizeof(int)*s1);
( , ). Matt Austern , sgi STL .

.508: 16.3.5.

: ( ). -- . .

, . "" O(log(N)), STL - , (10, ) , , O(N), . , reserve(), , .


.526: 17.1.4.1.

, C- , .

"", , char* STL : -- , - . , :

void f(set<char*>& cset)
{
 for (;;) {
     char word[100];

     //    word ...

     cset.insert(word);  // :      
                         //   
 }
}
string:
void f(set<string>& cset)
{
 for (;;) {
     char word[100];

     //    word ...

     cset.insert(word);  // OK:  string
 }
}
char* STL , .. . sgi STL char* :
struct ltstr
{
  bool operator()(const char* s1, const char* s2) const
  {
    return strcmp(s1, s2) < 0;
  }
};

int main()
{
  const int N = 6;
  const char* a[N] = {"isomer", "ephemeral", "prosaic",
                      "nugatory", "artichoke", "serif"};

  set<const char*, ltstr> A(a, a + N);

  //  ..
}
, C-, .

!


.541: 17.4.1.2.

, pair.

, , , :

template <class T1,class T2>
pair<T1,T2> std::make_pair(const T1& t1, const T2& t2)
{
 return pair<T1,T2>(t1,t2);
}
: -, , .. . - :
char c=1;
int  i=2;

//   ""
pair(c,i);            //  -- pair<char,int>  
pair<char,int>(c,i);  // 
make_pair(c,i);       // 

.543: 17.4.1.3.

operator[]().

, , .. , , , -- .


.555: 17.5.3.3.

, .

, : " " .

,

f<int>();  // f -- -
obj.f<int>();  // f -- -,  
, !

, - , :

  1. template , - ;
  2. , ( ) , aC++ HP. , , , .
" " B.13.6. template .

.556: 17.6.

... hash_map.

"", ! , " hash_map" . , STL, C++, hash_map ( ). - , hash_map , , -- . , ...


.583: 18.4.4.1.

? ?

(, , , )?

list<int>::const_iterator p=find_if(c.begin(),c.end(),bind2nd(less<int>(),7));
:
list<int>::const_iterator p;
for (p=c.begin(); p!=c.end(); ++p)
    if (*p<7) break;
? -, . ? , bind2nd(). *p>=5 && *p<100, , , , find_if() . : , .

, . , , - , .


.584: 18.4.4.2. -

, - ...

- mem_fun(). ,

for_each(lsp.begin(),lsp.end(),mem_fun(&Shape::draw));  //   
. , mem_fun() , , (design pattern). -- . ?

, ? bind2nd(), ? , ? -, .

, mem_fun() - . , , , -- .


.592: 18.6. ,

...

! .. remove(), ( ) ?!

, , , -- !


.592: 18.6.1.

...

, , ( ) C memcpy() memmove(). ? , . , : STL ( sgi) vector<int> memmove().

__type_traits<> -- . ( ) / POD , .

C++ POD (Plain Old Data). ? POD -- , ( memmove(), ). ( ) .

? , , Date POD :

class Date {
      int day, mon, year;
      //  
      long val;  // yyyymmdd
 public:
      // ...
};
__type_traits<>:
template<> struct __type_traits<Date> {
 // ...
};
: __type_traits<> -- , . , .

.622: 19.2.5.

, * *(current-1)...

, :

24.4.1.3.3 operator* [lib.reverse.iter.op.star]

reference operator*() const;
  1. :
    Iterator tmp = current;
    return *--tmp;
.. , , , . , ( , ) ? - :

I don't think anyone would use a reverse iterator if an iterator was an alternative, but then you never know what people might know. When you actually need to go through a sequence in reverse order a reverse iterator is often quite efficient compared to alternatives. Finally, there may not be any overhead because where the iterator is a vector the temporary isn't hard to optimize into a register use. One should measure before worrying too much about overhead.

, - , , , . , . , , , - . , .

, - , ().

, .

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <list>

long Count, Var;

typedef std::list<int> list_type;
list_type lst;

void f1()
{
 for (list_type::reverse_iterator ri=lst.rbegin(), rend=lst.rend(); ri!=rend;
      ++ri)
     Var+=*ri;
}

void f2()
{
 list_type::iterator i=lst.end(), beg=lst.begin();
 if (i!=beg) {
    do {
       --i;
       Var+=*i;
    } while (i!=beg);
 }
}

int main(int argc, char** argv)
{
 if (argc>1) Count=atol(argv[1]);

 for (int i=0; i<10000; i++)
     lst.push_back(i);

 clock_t c1, c2;
 {
  c1=clock();

  for (long i=0; i<Count; i++)
      for (long j=0; j<1000; j++)
          f1();

  c2=clock();
  printf("f1(): %ld ths calls per %.1f sec\n", Count, double(c2-c1)/CLK_TCK);
 }
 {
  c1=clock();

  for (long i=0; i<Count; i++)
      for (long j=0; j<1000; j++)
          f2();

  c2=clock();
  printf("f2(): %ld ths calls per %.1f sec\n", Count, double(c2-c1)/CLK_TCK);
 }
}
10 000 ( ) ( f1()) ( f2()) . , "" 45% 2.4 .

: ? :

void f1()
{
 for (list_type::iterator i=lst.begin(), end=lst.end(); i!=end; ++i)
     Var+=*i;
}

void f2()
{
 for (list_type::iterator i=lst.begin(), end=lst.end(); i!=end; i++)
     Var+=*i;
}
: , , , 5 - 30 .

, , .


.634: 19.4.1.

, C++ .

: ? C++ ""? -. :

Something that would allow a copy constructor to be defined using a user-defined reference object.

-, .


.637: 19.4.2. ,

template<class T>
T* Pool_alloc<T>::allocate(size_type n, void* =0)
{
 if (n==1) return static_cast<T*>(mem_alloc());
 // ...
}

, . allocate<>() n!=1? mem_alloc()? , . ? Pool_alloc<char>. Pool:

Pool::Pool(unsigned int sz)
      : esize(sz<sizeof(Link*) ? sizeof(Link*) : sz)
{
 // ...
}
, sz==sizeof(char) char sizeof(Link*) . "" ! .. X, sizeof(X)<sizeof(Link*) , deallocate<>(), , .

.641: 19.4.4.

template<class T, class A> T* temporary_dup(vector<T,A>& v)
{
 T* p=get_temporary_buffer<T>(v.size()).first;
 if (p==0) return 0;
 copy(v.begin(),v.end(),raw_storage_iterator<T*,T>(p));
 return p;
}

, , .. get_temporary_buffer<>() . .. get_temporary_buffer<>() , , :

template<class T, class A> T* temporary_dup(vector<T,A>& v)
{
 pair<T*,ptrdiff_t> p(get_temporary_buffer<T>(v.size()));

 if (p.second<v.size()) {
    if (p.first) return_temporary_buffer(p.first);
    return 0;
 }

 copy(v.begin(),v.end(),raw_storage_iterator<T*,T>(p));
 return p.first;
}

.647: 20.2.1.

assign(s,n,x) assign(s[i],x) n x s.
compare() lt() eq().

, char_traits<char> , , lt(), eq(), assign(s[i],x), memcmp() memset(), , , . .. strcmp() , , , string 30% , C char* strcmp(). : string char .


.652: 20.3.4.

basic_string , ().

, , basic_string::c_str(). , () [const] char* [const] string&, , "" , .

, , char* C . , , , , , '-' '+', .

, , string , , , memcpy(), "" .


.655: 20.3.6.

, , , - . , .

(.. ). , sgi STL 3.2 , . , .

, - . , , .. ( Herb Sutter Reference Counting - Part III), -- .

, : , , , .

, , , , const string&.


.676: 21.2.2.

... :
(cerr.operator<<("x=")).operator<<(x);

: - -, :

operator<<(cerr,"x=").operator<<(x);
! : , - , -- !

, , , .


.687: 21.3.4.

, C -- , -- . , , C++ -- .

: C++ . C, -- (, , FILE* C, C++ ; , !). :

#include <stdio.h>
#include <time.h>
#include <io.h>  //  open()
#include <fcntl.h>
#include <iostream>
#include <fstream>

using namespace std;

void workc(char*);
void workcpp(char*);
void work3(char*);

int main(int argc, char **argv)
{
 if (argc==3)
    switch (*argv[2]-'0') {
           case 1: {
                workc(argv[1]);
                break;
           }
           case 2: {
                workcpp(argv[1]);
                break;
           }
           case 3: {
                work3(argv[1]);
                break;
           }
    }
}

void workc(char* fn)
{
 FILE* fil=fopen(fn, "rb");
 if (!fil) return;

 time_t t1; time(&t1);

 long count=0;
 while (getc(fil)!=EOF)
       count++;

 time_t t2; time(&t2);

 fclose(fil);
 cout<<count<<" bytes per "<<t2-t1<<" sec.\n" ;
}

void workcpp(char* fn)
{
 ifstream fil(fn, ios_base::in|ios_base::binary);
 if (!fil) return;

 time_t t1; time(&t1);

 long count=0;
 while (fil.get()!=EOF)
       count++;

 time_t t2; time(&t2);
 cout<<count<<" bytes per "<<t2-t1<<" sec.\n" ;
}

class File {
      int            fd;           //  
      unsigned char  buf[BUFSIZ];  //   
      unsigned char* gptr;         //   
      unsigned char* bend;         //  

      int uflow();
 public:
      File(char* fn) : gptr(0), bend(0) { fd=open(fn, O_RDONLY|O_BINARY); }
      ~File() { if (Ok()) close(fd); }

      int Ok() { return fd!=-1; }

      int gchar() { return (gptr<bend) ? *gptr++ : uflow(); }
};

int File::uflow()
{
 if (!Ok()) return EOF;

 int rd=read(fd, buf, BUFSIZ);
 if (rd<=0) {  //   EOF
    close(fd);
    fd=-1;

    return EOF;
 }

 gptr=buf;
 bend=buf+rd;

 return *gptr++;
}

void work3(char* fn)
{
 File fil(fn);
 if (!fil.Ok()) return;

 time_t t1; time(&t1);

 long count=0;
 while (fil.gchar()!=EOF)
       count++;

 time_t t2; time(&t2);

 cout<<count<<" bytes per "<<t2-t1<<" sec.\n" ;
}