:


---------------------------------------------------------------
 © Copyright  , 2000
    , 12 Oct 2004
 Origin: http://ders.stml.net/cpp/
---------------------------------------------------------------

C++ 3rd:


43 1.3.1.
73 2.5.5.
79 2.7.2.
128 5.1.1.
192 7.4.
199 7.6.
202 7.7.
296 10.4.6.2. -
297 10.4.7.
316 11.3.1. - -
328 11.5.1.
333 11.7.1.
337 11.9.
344 11.12. String
351 12.2.
361 12.2.6.
382 13.2.3.
399 13.6.2. -
419 14.4.1.
421 14.4.2. auto_ptr
422 14.4.4. new
431 14.6.1.
431 14.6.3.
460 15.3.2.
461 15.3.2.1.
475 15.5.
477 15.6.
478 15.6.
479 15.6.1.
480 15.6.2. " "
498 16.2.3. STL-
505 16.3.4.
508 16.3.5.
526 17.1.4.1.
541 17.4.1.2.
543 17.4.1.3.
555 17.5.3.3.
556 17.6.
583 18.4.4.1.
584 18.4.4.2. -
592 18.6. ,
592 18.6.1.
622 19.2.5.
634 19.4.1.
637 19.4.2. ,
641 19.4.4.
647 20.2.1.
652 20.3.4.
655 20.3.6.
676 21.2.2.
687 21.3.4.
701 21.4.6.3. ,
711 21.6.2.
773 23.4.3.1. 1:
879 .5.
931 B.13.2.
935 B.13.6. template

" " C++. ? , C++. , . " C++", 3 . , C++ " C++", C++ -- , - C++ - . , , .

( ) C++ 3rd , , . - , , .

. , " C++" , .. , C++. C++ 3rd, C++. , () , , .

- , : Bjarne Stroustrup "The C++ Programming language", 3rd edition / C++ (ISO/IEC 14882 Programming languages - C++, First edition, 1998-09-01). , , C++ . , , C++ Standard Core Issues List C++ Standard Library Issues List .

STL, . , , .

, "The C programming Language" by Brian W. Kernighan and Dennis M. Ritchie, 2 , -- !

, .


.43: 1.3.1.

new, delete, type_id, dynamic_cast, throw try, C++ .

, , " ". / () , / , / , , .

(, , , " " ):

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

struct A {
       A();
       ~A();
};

void ACon();
void ADes();

void f1()
{
 A a;
}

void f2()
{
 ACon();
 ADes();
}

long Var, Count;

A::A()  { Var++; }
A::~A() { Var++; }

void ACon() { Var++; }
void ADes() { Var++; }

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<1000000; j++)
          f1();

  c2=clock();
  printf("f1(): %ld mlns 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<1000000; j++)
          f2();

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

-- . , f1() f2().

; , 10 !

inline? :

struct A {
       A()  { Var++; }
       ~A() { Var++; }
};

void f1()
{
 A a;
}

void f2()
{
 Var++;
 Var++;
}
f1() f2() . , .

? abstraction penalty, .. (-) .

abstraction penalty .

void f1()
{
 A a;
}
void f1()  // 
{
 A::A();
 A::~A();
}
:
void f2()
{
 ACon();
 ADes();
}
-- ! , :
void f1()
{
 A a;
 f();
}

void f2()
{
 ACon();
 f();
 ADes();
}
, ? -- , .. f1()
void f1()  // 
{
 A::A();

 try {
     f();
 }
 catch (...) {
       A::~A();
       throw;
 }

 A::~A();
}
.. , , . .. , , . f1() (, "" /):
void f1()  // 
{
 A::A();

 try {
     // 
 }
 catch (...) {
       A::~A();
       throw;
 }

 A::~A();
}
, , " ", . , inline . STL, , , .

abstraction penalty -- " ".


.73: 2.5.5.

, vtbl .

, .. "" vtbl.

. (.. ) B1:

struct B1 {  //   struct      
       int a1;
       int b1;

       virtual ~B1() { }
};
vptr ( ) . B1 :
vptr_1  //   vtbl  B1
a1      //   
b1
B2 D
struct D: B1, B2 {
       virtual ~D() { }
};
:
vptr_d1  //   vtbl  D,  B1   vptr_1
a1       //   B1 
b1
vptr_d2  //   vtbl  D,  B2   vptr_2
a2       //   B2 
b2
vptr? , , .

, , , : " "? , . , . .. :

D d;
B2* ptr=&d;
ptr vptr_d2. vptr D vptr_d1. , , . ? B1 B2 vtbl , D . .. vtbl D : B1, B2 .

, , , .

, , , : vptr this vtbl. , .

, .

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

struct B {
       void f();
       virtual void vf();
};

struct D : B {
       void vf();  //  B::vf
};

void f1(B* ptr)
{
 ptr->f();
}

void f2(B* ptr)
{
 ptr->vf();
}

long Var, Count;

void B::f()  { Var++; }
void B::vf() { }

void D::vf() { Var++; }

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

 clock_t c1,c2;

 D d;
 {
  c1=clock();

  for (long i=0; i<Count; i++)
      for (long j=0; j<1000000; j++)
          f1(&d);

  c2=clock();
  printf("f1(): %ld mlns 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<1000000; j++)
          f2(&d);

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

"" , .. ( )

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

struct B {
       int ackf(int x, int y);
       virtual int vackf(int x, int y);
};

struct D : B {
       int vackf(int x, int y);  //  B::vackf
};

void f1(B* ptr)
{
 ptr->ackf(3, 5);  // 42438 !
}

void f2(B* ptr)
{
 ptr->vackf(3, 5);  // 42438 !
}

int B::ackf(int x, int y)
{
 if (x==0) return y+1;
 else if (y==0) return ackf(x-1, 1);
      else return ackf(x-1, ackf(x, y-1));
}

int B::vackf(int x, int y) { return 0; }

int D::vackf(int x, int y)
{
 if (x==0) return y+1;
 else if (y==0) return vackf(x-1, 1);
      else return vackf(x-1, vackf(x, y-1));
}

long Count;

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

 clock_t c1,c2;

 D d;
 {
  c1=clock();

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

  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(&d);

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

.79: 2.7.2.

C++ , , , :
char vc1[200];
char vc2[500];

void f()
{
 copy(&vc1[0],&vc1[200],&vc2[0]);
}

, , . - :

The issue is whether taking the address of one-past-the-last element of an array is conforming C and C++. I could make the example clearly conforming by a simple rewrite:
	copy(vc1,vc1+200,vc2);
However, I don't want to introduce addition to pointers at this point of the book. It is a surprise to most experienced C and C++ programmers that &vc1[200] isn't completely equivalent to vc1+200. In fact, it was a surprise to the C committee also and I expect it to be fixed in the upcoming revision of the standard. (also resolved for C9x - bs 10/13/98).

, C C++ , . :

	copy(vc1,vc1+200,vc2);
, . C C++ , &vc1[200] vc1+200. , C , , .

? C++ :

&vc1[200] -> &(*((vc1)+(200))) -> &*(vc1+200)
&*(vc1+200) == vc1+200 ?

It is false in C89 and C++, but not in K&R C or C9x. The C89 standard simply said that &*(vc1+200) means dereference vc1+200 (which is an error) and then take the address of the result, and the C++ standard copiled the C89 wording. K&R C and C9x say that &* cancels out so that &*(vc1+200) == vc2+200.

89 C++, K&R C 9. 89 , &*(vc1+200) vc1+200 ( ) . C++ 89. K&R C 9 , &* , .. &*(vc1+200) == vc1+200.

, &*(vc1+200) *(vc1+200) , .. ( ) &.


.128: 5.1.1.

, NULL,
const int NULL=0;

, , ( ) NULL , 0 -- .

, NULL static_cast<SomeType*>(0) .

, , NULL . , :

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

void error(int stat ...)
{
 va_list ap;
 va_start(ap, stat);

 while (const char* sarg=va_arg(ap, const char *))
       printf("%s", sarg);

 va_end(ap);
 exit(stat);
}

int main()
{
 error(1, " ", "", NULL);  // , !
                                            //  NULL  
                                            // static_cast<const char *>(0)
}
(, ) NULL 0L ( 0) , sizeof(void*)==sizeof(long)>sizeof(int).

.192: 7.4.

...

[2] :

  1. , "" (" ") (, bool int, char int, short int; B.6.1), float double.
, - , :
struct A {
 private:
       void f(int);
 public:
       void f(...);
};

void g()
{
 A a;
 a.f(1);  // :  A::f(int), 
          //   g() 
}
, : - .

.199: 7.6.

, va_start(), va_end(). , va_start() , .

.

, . , , .

, va_end() . , / C++ , .. "" std::cout va_end() .


.202: 7.7.

, cmp3 ssort() , ssort() mytype*.

, . : , cmp3 ssort() , cmp3() mytype*.


.296: 10.4.6.2. -

, , .

, ? ? - :

The reason for "discriminating against" floating points in constant expressions is that the precision of floating point traditionally varied radically between processors. In principle, constant expressions should be evaluated on the target processor if you are cross compiling.

"" , . , -, .

.. - , ( ) .

, - (, , ) , ..

class Curious {
      static const float c5=7.0;
};
() .

.297: 10.4.7.

( ) .

, . , :

#include <stdio.h>

struct A {  //  
       int a;
       A(int a_) : a(a_) { printf("%d\n",a); }
};

void f()
{
 static int vals[]={2, 0, 0, 4};
 static int curr=0;

 struct A_local : public A {  //  
        A_local() : A(vals[curr++]) { }
 };

 A_local arr[4];
 //     A arr[4];
}

int main()
{
 f();
}
.. , :

9.8 [class.local]

  1. ; (local) . (enclosing scope). , . , , extern , . :
    int x;
    void f()
    {
     static int s;
     int x;
     extern int g();
    
     struct local {
            int g() { return x; }   // , auto x
            int h() { return s; }   // OK
            int k() { return ::x; } // OK
            int l() { return g(); } // OK
     };
     //  ...
    }
    
    local* p = 0;  // :  local   
  2. , (. 11 [class.access]). - , , .
  3. Y X X , (scope), X. .
  4. -.

.316: 11.3.1. - -

complex r1=x+y+z;  // r1=operator+(x,operator+(y,z))

:

complex r1=x+y+z;  // r1=operator+(operator+(x,y),z)
: (x+y)+z.

.328: 11.5.1.

:
//  f()    

class X {
      friend void f();          // 
      friend void h(const X&);  //     
};

void g(const X& x)
{
 f();   //  f()    
 h(x);  // h() --  X
}
8- , f , - f() X f , f() g() .

.333: 11.7.1.

String s1='a';  // :    char  String
String s2(10);  // :    10 
...

. .

X a=b;
a X X. :
  1. b X. :
    X a(b);
  2. b X . X, :
    X a(X(b));
    explicit-, .
, :

12.8 [class.copy]

  1. , , ( cv-), , , . return , ( cv-) , , . , , .
, .
#include <stdio.h>
#include <string.h>

struct A {
       static const int nsize=10;

       char n[nsize];

       A(char cn)
       {
        n[0]=cn;
        n[1]=0;

        printf("%5s.A::A()\n", n);
       }

       A(const A& a)
       {
        if (strlen(a.n)<=nsize-2) {
           n[0]='?';
           strcpy(n+1, a.n);
        }
        else strcpy(n, "");

        printf("%5s.A::A(const A& %s)\n", n, a.n);
       }

       ~A() { printf("%5s.A::~A()\n", n); }

       A& operator=(const A& a)
       {
        if (strlen(a.n)<=nsize-2) {
           n[0]='=';
           strcpy(n+1, a.n);
        }
        else strcpy(n, "");

        printf("%5s.A::operator=(const A& %s)\n", n, a.n);
        return *this;
       }
};

A f1(A a)
{
 printf("A f1(A %s)\n", a.n);
 return a;
}

A f2()
{
 printf("A f2()\n");
 A b('b');
 return b;
}

A f3()
{
 printf("A f3()\n");
 return A('c');
}

int main()
{
 {
  A a('a');
  A b='b';
  A c(A('c'));
  A d=A('d');
 }
 printf("----------\n");
 {
  A a('a');
  A b=f1(a);
  printf("b  %s\n", b.n);
 }
 printf("----------\n");
 {
  A a=f2();
  printf("a  %s\n", a.n);
 }
 printf("----------\n");
 {
  A a=f3();
  printf("a  %s\n", a.n);
 }
}
, main() a, b, c d. :
    a.A::A()
    b.A::A()
    c.A::A()
    d.A::A()
    d.A::~A()
    c.A::~A()
    b.A::~A()
    a.A::~A()
, , , :
    ...
    c.A::A()
   ?c.A::A(const A& c)
    c.A::~A()
    d.A::A()
    d.A::~A()
   ?c.A::~A()
    ...
.. A c(A('c')) A tmp('c'), c(tmp). , f1() :
    a.A::A()
   ?a.A::A(const A& a)
A f1(A ?a)
  ??a.A::A(const A& ?a)
   ?a.A::~A()
b  ??a
  ??a.A::~A()
    a.A::~A()
a ?a, f1() . , f1() ?a -- ??a, . - : b ??a, .. main() b -- , f1() ??a, ( : , b ???a).

-- , . f2() f3():

A f2()
    b.A::A()
   ?b.A::A(const A& b)
    b.A::~A()
a  ?b
   ?b.A::~A()
----------
A f3()
    c.A::A()
a  c
    c.A::~A()
f3() , f2() -- ! , .

, .. ( !).

-- . :

#include <stdio.h>
#include <string.h>

struct A {
       static const int nsize=10;
       static int tmpcount;

       int val;
       char n[nsize];

       A(int val_) : val(val_)  //    
       {
        sprintf(n, "_%d", ++tmpcount);
        printf("%5s.A::A(int %d)\n", n, val);
       }

       A(char cn, int val_) : val(val_)
       {
        n[0]=cn;
        n[1]=0;

        printf("%5s.A::A(char, int %d)\n", n, val);
       }

       A(const A& a) : val(a.val)
       {
        if (strlen(a.n)<=nsize-2) {
           n[0]='?';
           strcpy(n+1, a.n);
        }
        else strcpy(n, "");

        printf("%5s.A::A(const A& %s)\n", n, a.n);
       }

       ~A() { printf("%5s.A::~A()\n", n); }

       A& operator=(const A& a)
       {
        val=a.val;

        if (strlen(a.n)<=nsize-2) {
           n[0]='=';
           strcpy(n+1, a.n);
        }
        else strcpy(n, "");

        printf("%5s.A::operator=(const A& %s)\n", n, a.n);
        return *this;
       }

       friend A operator+(const A& a1, const A& a2)
       {
        printf("operator+(const A& %s, const A& %s)\n", a1.n, a2.n);
        return A(a1.val+a2.val);
       }
};

int A::tmpcount;

int main()
{
 A a('a', 1), b('b', 2), c('c', 3);
 A d=a+b+c;
 printf("d  %s\n", d.n);
 printf("d.val=%d\n", d.val);
}
:
    a.A::A(char,int 1)
    b.A::A(char,int 2)
    c.A::A(char,int 3)
operator+(const A& a,const A& b)
   _1.A::A(int 3)
operator+(const A& _1,const A& c)
   _2.A::A(int 6)
   _1.A::~A()
d  _2
d.val=6
   _2.A::~A()
    c.A::~A()
    b.A::~A()
    a.A::~A()
, .
 A d('d',0);
 d=a+b+c;
:
    a.A::A(char,int 1)
    b.A::A(char,int 2)
    c.A::A(char,int 3)
    d.A::A(char,int 0)
operator+(const A& a,const A& b)
   _1.A::A(int 3)
operator+(const A& _1,const A& c)
   _2.A::A(int 6)
  =_2.A::operator=(const A& _2)
   _2.A::~A()
   _1.A::~A()
d  =_2
d.val=6
  =_2.A::~A()
    c.A::~A()
    b.A::~A()
    a.A::~A()

.337: 11.9.

, , -- operator()() Add(z).

, : - , . .

, , - for_each()

template <class InputIter, class Function>
Function for_each(InputIter first, InputIter last, Function f) {
 for ( ; first != last; ++first)
     f(*first);
 return f;
}
sgi STL ( ). , ( -) .

for_each() c Add(z),

for_each(ll.begin(), ll.end(), Add(z));
Function -- Add, .. , Add(z). for_each() :
Add for_each(InputIter first, InputIter last, Add f) {
 for ( ; first != last; ++first)
     f.operator()(*first);
 return f;
}
.. for_each() Add(z), . , for_each() Add::operator()(complex&). , InputIter , .

? , -- -, . , ,

Add for_each(...) {
 for (...)
     Add(z).operator()(*first);
 return f;
}
, , , : , .

.344: 11.12. String

, , s.operator[](1) Cref(s,1).

. const const -? ?

:

struct X {
	 void f(int);
	 void f(int) const;
};

void h()
{
 const X cx;
 cx.f(1);

 X x;
 x.f(2);
}
, - this,
// 
struct X {
	 void f(      X *const this);
	 void f(const X *const this);
};

void h()
{
 const X cx;
 X::f(&cx,1);

 X x;
 X::f(&x,2);
}
. , .

.351: 12.2.

, -- . , , .

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


.361: 12.2.6.

, ...

, , . " " . :

#include <stdio.h>

struct B1 {
       int b1;  // 
       virtual ~B1() { }
};

struct B2 {
       int b2;  // 
       virtual void vfun() { }
};

struct D : B1, B2 {  //     
       virtual void vfun() { printf("D::vfun(): this=%p\n", this); }
};

int main()
{
 D d;

 D* dptr=&d;
 printf("dptr\t%p\n", dptr);
 dptr->vfun();

 B2* b2ptr=&d;
 printf("b2ptr\t%p\n", b2ptr);
 b2ptr->vfun();
}
:
dptr    0x283fee8
D::vfun(): this=0x283fee8
b2ptr   0x283feec
D::vfun(): this=0x283fee8
.. dptr, D::vfun() this=0x283fee8. , () b2ptr, () , D::vfun() , D::vfun() this.

? ,

struct D : B1, B2 {
       virtual void vfun(D *const this)  //  
       {
        // ...
       }
};
ptr->vfun() (*vtbl[index_of_vfun])(ptr), b2ptr==0x283feec==this!=0x283fee8.

: ? , (D::vfun() ) (ptr==0x283fee8) (ptr==0x283feec), , this (this==0x283fee8) .

, vtbl , , , . , , :

  1. vtbl -- vdelta. vtbl , ptr:
    addr=vtbl[index].vaddr;    //    vfun
    delta=vtbl[index].vdelta;  //  ,     vfun
    (*addr)(ptr+delta);        //  vfun
    vtbl : , ptr, vdelta . -- ANSI C , C++ -> C .
  2. , ptr ( ):
    vfun_entry_0:
      // ...
      //   vfun
      // ...
      return;
    
    vfun_entry_1:
      ptr+=delta_1;       //   ptr
      goto vfun_entry_0;  //     vfun
    vtbl . ANSI C.
C++: Under the Hood. , MSVC.

.382: 13.2.3.

, .

-- (internal linkage).


.399: 13.6.2. -

, (, , ).

-... , . , :

Curiously enough, a template constructor is never used to generate a copy constructor, so without the explicitly declared copy constructor, a default copy constructor would have been generated.

, - , .. .

, " " "-".


.419: 14.4.1.

, , , .

, , , try/catch, -- . -, ? :

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

void ResourceAcquire();
void ResourceRelease();
void Work();

struct RAII {
       RAII()  { ResourceAcquire(); }
       ~RAII() { ResourceRelease(); }
};

void f1()
{
 ResourceAcquire();

 try { Work(); }
 catch (...) {
       ResourceRelease();
       throw;
 }

 ResourceRelease();
}

void f2()
{
 RAII raii;
 Work();
}

long Var, Count;

void ResourceAcquire() { Var++; }
void ResourceRelease() { Var--; }
void Work() { Var+=2; }

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<1000000; j++)
          f1();

  c2=clock();
  printf("f1(): %ld mln 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<1000000; j++)
          f2();

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

? , -. ! , Structured Exception Handling / (multithreading). , ...

Internet exception handling (EH) C++ , . , EH C++ .

, " " , . , .. EH, (, , ) () (, (E)IP Intel-) .

(, , EH) , EH Control Flow Graph, .. , .

, EH 5%, .

! , "" -- : " "...


.421: 14.4.2. auto_ptr

<memory> auto_ptr ...

, () auto_ptr, ( 4 ).

( (destructive copy semantics)), auto_ptr : auto_ptr , auto_ptr ( 0 ). .. auto_ptr , const auto_ptr .

auto_ptr <memory> :

template<class X> class std::auto_ptr {
	//  
	template <class Y> struct auto_ptr_ref { /* ... */ };

	X* ptr;
public:
	typedef X element_type;

	explicit auto_ptr(X* p =0) throw() { ptr=p; }
	~auto_ptr() throw() { delete ptr; }

	//  :    
	//    

	// ,  a.ptr=0
	auto_ptr(auto_ptr& a) throw();

	// ,  a.ptr=0
	template<class Y> auto_ptr(auto_ptr<Y>& a) throw();

	// ,  a.ptr=0
	auto_ptr& operator=(auto_ptr& a) throw();

	// ,  a.ptr=0
	template<class Y> auto_ptr& operator=(auto_ptr<Y>& a) throw();

	X& operator*() const throw() { return *ptr; }
	X* operator->() const throw() { return ptr; }

	//  
	X* get() const throw() { return ptr; }

	//  
	X* release() throw() { X* t = ptr; ptr=0; return t; }

	void reset(X* p =0) throw() { if (p!=ptr) { delete ptr; ptr=p; } }

	//   auto_ptr_ref
	auto_ptr(auto_ptr_ref<X>) throw();

	//   auto_ptr_ref
	template<class Y> operator auto_ptr_ref<Y>() throw();

	//    auto_ptr
	template<class Y> operator auto_ptr<Y>() throw();
};
auto_ptr_ref -- , auto_ptr . - - auto_ptr<D> auto_ptr<B> D* B*, :
void g(Circle* pc)
{
 auto_ptr<Circle> p2 = pc;  //  p2   

 auto_ptr<Circle> p3 = p2;  //  p3   ,
                            //  p2  

 p2->m = 7;                 //  : p2.get()==0

 Shape* ps = p3.get();      //  

 auto_ptr<Shape> aps = p3;  //    
                            //  

 auto_ptr<Circle> p4 = pc;  // :  p4    
}
auto_ptr ; , .

, , sort(). :

// :  auto_ptr  
void h(vector<auto_ptr<Shape> >& v)
{
 sort(v.begin(),v.end());  //   :    
}
, auto_ptr "" , -- , .

.422: 14.4.4. new

, -- .

.. , :

5.3.4. New [expr.new]

  1. - , , . , ( , ; , , , ).

.431: 14.6.1.

, typedef .

: ? - :

The reason is the exception spacification is not part of the type; it is a constraint that is checked on assignment and exforced at run time (rather than at compile time). Some people would like it to be part of the type, but it isn't. The reason is to avoid difficulties when updating large systems with parts from different sources. See "The Design and Evolution of C++" for details.

, ; ( ). , , . , , , . " C++" .

, -- C++. , C++ ( exception safety) . , , Java, C++, .

, exception safe : ? .

, , nothrow:

( !) . .

.431: 14.6.3.

std::bad_exception . - :

The standard doesn't support the mapping of exceptions as I describe it in 14.6.3. It specifies mapping to std::bad_exception for exceptions thrown explicitly within an unexpected() function. This makes std::bad_exception an ordinary and rather pointless exception. The current wording does not agree with the intent of the proposer of the mechanism (Dmitry Lenkov of HP) and what he thought was voted in. I have raised the issue in the standards committee.

, 14.6.3. std::bad_exception , unexpected(). std::bad_exception , . () HP. issue .

, , :

15.5.2 unexpected() [except.unexpected]

  1. ,
    	void unexpected();
    (stack unwinding).
  2. unexpected() , () . , , . , : std::bad_exception (18.6.2.1), terminate(), () std::bad_exception .
  3. , , . std::bad_exception, std::bad_exception unexpected().

.460: 15.3.2.

class XX : B { /* ... */ };  // B --   
class YY : B { /* ... */ };  // B --   

, :

class XX : B { /* ... */ };  // B --  
struct YY : B { /* ... */ };  // B --  
.. , B , : , , -- .

, -- , , .


.461: 15.3.2.1.

... , .

, , , , , . .. : ... .


.475: 15.5.

...

, , . .

, , C++ :

struct S {
       int i;
       void f();
};

void g()
{
 cout<<&S::i;  // : operator<<     int S::*
 cout<<&S::f;  // : operator<<     void (S::*)()
}
. Andrew Koenig , /, , - (, , , ). , - , .. -- , .

:

#include <string.h>
#include <stdio.h>

struct S {
       int i1;
       int i2;

       void f1();
       void f2();

       virtual void vf1();
       virtual void vf2();
};

const int SZ=sizeof(&S::f1);

union {
      unsigned char c[SZ];
      int i[SZ/sizeof(int)];
      int S::* iptr;
      void (S::*fptr)();
} hack;

void printVal(int s)
{
 if (s%sizeof(int)) for (int i=0; i<s; i++) printf(" %02x", hack.c[i]);
 else for (int i=0; i<s/sizeof(int); i++)
          printf(" %0*x", sizeof(int)*2, hack.i[i]);

 printf("\n");
 memset(&hack, 0, sizeof(hack));
}

int main()
{
 printf("sizeof(int)=%d sizeof(void*)=%d\n", sizeof(int), sizeof(void*));

 hack.iptr=&S::i1;
 printf("sizeof(&S::i1 )=%2d value=", sizeof(&S::i1));
 printVal(sizeof(&S::i1));

 hack.iptr=&S::i2;
 printf("sizeof(&S::i2 )=%2d value=", sizeof(&S::i2));
 printVal(sizeof(&S::i2));

 hack.fptr=&S::f1;
 printf("sizeof(&S::f1 )=%2d value=", sizeof(&S::f1));
 printVal(sizeof(&S::f1));

 hack.fptr=&S::f2;
 printf("sizeof(&S::f2 )=%2d value=", sizeof(&S::f2));
 printVal(sizeof(&S::f2));

 hack.fptr=&S::vf1;
 printf("sizeof(&S::vf1)=%2d value=", sizeof(&S::vf1));
 printVal(sizeof(&S::vf1));

 hack.fptr=&S::vf2;
 printf("sizeof(&S::vf2)=%2d value=", sizeof(&S::vf2));
 printVal(sizeof(&S::vf2));
}

void S::f1() {}
void S::f2() {}

void S::vf1() {}
void S::vf2() {}
hack, ( ), printVal(), .

, :

sizeof(int)=4 sizeof(void*)=4
sizeof(&S::i1 )= 8 value= 00000005 00000000
sizeof(&S::i2 )= 8 value= 00000009 00000000
sizeof(&S::f1 )=12 value= 004012e4 00000000 00000000
sizeof(&S::f2 )=12 value= 004012ec 00000000 00000000
sizeof(&S::vf1)=12 value= 004012d0 00000000 00000000
sizeof(&S::vf2)=12 value= 004012d8 00000000 00000000

sizeof(int)=4 sizeof(void*)=4
sizeof(&S::i1 )= 4 value= 00000001
sizeof(&S::i2 )= 4 value= 00000005
sizeof(&S::f1 )= 8 value= ffff0000 004014e4
sizeof(&S::f2 )= 8 value= ffff0000 004014f4
sizeof(&S::vf1)= 8 value= 00020000 00000008
sizeof(&S::vf2)= 8 value= 00030000 00000008

sizeof(int)=4 sizeof(void*)=4
sizeof(&S::i1 )= 4 value= 00000004
sizeof(&S::i2 )= 4 value= 00000008
sizeof(&S::f1 )= 4 value= 00401140
sizeof(&S::f2 )= 4 value= 00401140
sizeof(&S::vf1)= 4 value= 00401150
sizeof(&S::vf2)= 4 value= 00401160
, int void*, , . ?
  1. - -- . , .
  2. , . , . , .
  3. -- -. , "" -- .
, - . ! , C++ : . .

- , .. "" (ffff0000 004014e4), -- (00020000 00000008). , , , int, -1 (ffff), , -- . - .

: ", , ? , ." , ! , : -.

, :

struct S {
       virtual void vf() { /* 1 */ }
               void f () { /* 2 */ }
};

void g(void (S::*fptr)(), S* sptr)
{
 (sptr->*fptr)();
}

int main()
{
 S s;
 g(S::vf, &s);
 g(S::f , &s);
}
:
void S_vf(S *const this) { /* 1 */ }
void S_f (S *const this) { /* 2 */ }

void S_vf_stub(S *const this)
{
 //    S::vf()
 (this->vptr[index_of_vf])(this);
}

void g(void (*fptr)(S *const), S* sptr)
{
 fptr(sptr);
}

int main()
{
 S s;
 g(S_vf_stub, &s);  //  :  S_vf !!!
 g(S_f      , &s);
}
C++ " -", , .. size_t, - ( ) . , , -, .

.477: 15.6.

// , p s , Employee::operator new()

: p , operator delete() , .. .

: operator delete(), ! .. :

void Employee::operator delete(void* p, size_t s)
{
 if (!p) return;  //   

 // ,  p   s  , 
 // Employee::operator new()    
 //   
}
, , p
template <class T> void std::allocator::deallocate(pointer p, size_type n);
. Pool::free 19.4.2. " , " .

.478: 15.6.

, ( ).

. ..

A::~A()
{
 //  
}
( )
// 
A::~A(A *const this, bool flag)
{
 if (this) {
    //  
    if (flag) delete(this, sizeof(A));
 }
}
void f(Employee* ptr)
{
 delete ptr;
}
// 
void f(Employee* ptr)
{
 Employee::~Employee(ptr, true);
}
.. Employee , .

.479: 15.6.1.

, new[] . , 10.3 "Array Allocation" "The Design and Evolution of C++" :

X X::operator new() X ( X , ).

X* p = new X[10];
X::operator new(), .. X[10] , X.

, .. X. , .. X -- X, , , X . , X::operator new() , , . , ? , , X[d] : , X[d][d2]?

, , , , , . , , . , , .. . .

, / :

class X {
      // ...
      void* operator new(size_t sz);    //  
      void operator delete(void* p);

      void* operator new[](size_t sz);  //  
      void operator delete[](void* p);
};
. , operator new[] ; . , . Laura Yaker Mentor Graphics , .

.480: 15.6.2. " "

... .

, " " . :

#include <stdio.h>

struct B1 {
       int b1;  // 
       virtual ~B1() { }
};

struct B2 {
       int b2;  // 

       virtual B2* vfun()
       {
        printf("B2::vfun()\n");  //     
        return this;
       }
};

struct D : B1, B2 {  //     
       virtual D* vfun()
       {
        printf("D::vfun(): this=%p\n", this);
        return this;
       }
};

int main()
{
 D d;

 D* dptr=&d;
 printf("dptr\t%p\n", dptr);

 void* ptr1=dptr->vfun();
 printf("ptr1\t%p\n", ptr1);

 B2* 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, , :
    • ( )
    • B::f D::f D::f D
    • cv- , , D::f cv-, 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" ;
}
. -- () , -- 1, 2 3, workc(), workcpp() work3() . , .. .

work3() File. "" - C -- FILE*. , workc() work3(), , , .

: .

? ! ( ) 11 !!!

, .

C getc() :

#define getc(f) ((--((f)->level) >= 0) ? (unsigned char)(*(f)->curp++) : _fgetc (f))
.. . -- -. C++ , : - , - ?!

: -- ! , ?

void workc(char* fn)
{
 // ...

 if (setvbuf(fil, 0, _IOFBF, LARGE_BUFSIZ)) return;

 // ...
}

void workcpp(char* fn)
{
 // ...

 char* buf=new char[LARGE_BUFSIZ];
 fil.rdbuf()->pubsetbuf(buf, LARGE_BUFSIZ);

 // ...

 delete [] buf;
}
, ! , , ( , ).

, , . , . , .. .

, , - , C++ .


.701: 21.4.6.3. ,

- , . , - . , , , ...printf() . ? dd.mm.yyyy:
int day= 31,
    mon= 1,
    year=1974;

printf("%02d.%02d.%d\n", day, mon, year);  // 31.01.1974

cout<<setfill('0')<<setw(2)<<day<<'.'<<setw(2)<<mon<<setfill(' ')<<'.'
    <<year<<"\n";  //  31.01.1974
, .

C C++ ? C++ -- . .. C++ , , , , ...printf(). :

cout<<c_form(day,"02")<<'.'<<c_form(mon,"02")<<'.'<<year<<'\n';
:
#include <ostream>

/**     c_form,    */
namespace c_form_private {

 typedef std::ios_base::fmtflags fmtflags;
 typedef std::ostream ostream;
 typedef std::ios_base ios;

 /**
  *     .
  */
 class Formatter {
       /**    */
       fmtflags newFlags;
       /**  */
       int width;
       /**  */
       int prec;
       /** - */
       char fill;
       /**   */
       fmtflags oldFlags;

  public:
       /**
        *  ,   .
        */
       Formatter(const char* form, int arg1, int arg2);

       /**
        *      , 
        * .
        */
       void setFormatting(ostream& os);

       /**
        *   ,   
        * setFormatting().
        */
       void restoreFormatting(ostream& os);
 };

 /**
  *  .
  */
 template <class T>
 class Helper {
       /**   */
       const T& val;
       /**    */
       mutable Formatter fmtr;

  public:
       /**
        *     .
        */
       Helper(const T& val_, const char* form, int arg1, int arg2) :
         val(val_), fmtr(form, arg1, arg2) {}

       /**
        *          .
        */
       void putTo(ostream& os) const;
 };

 template <class T>
 void Helper<T>::putTo(ostream& os) const
 {
  fmtr.setFormatting(os);
  os<<val;
  fmtr.restoreFormatting(os);
 }

 /**
  *     Helper  .
  */
 template <class T>
 inline ostream& operator<<(ostream& os, const Helper<T>& h)
 {
  h.putTo(os);
  return os;
 }
}

/**
 * -,    , 
 *      ostream.  
 *      .
 * @param val   
 * @param form  : [-|0] [|*] [.(|*)] [e|f|g|o|x]
 * @param arg1  ,    .
 * @param arg2  ,  .
 * @throws std::invalid_argument    form 
 *         .
 */
template <class T>
inline c_form_private::Helper<T> c_form(const T& val, const char* form,
  int arg1=0, int arg2=0)
{
 return c_form_private::Helper<T>(val, form, arg1, arg2);
}
-:
#include "c_form.hpp"
#include <stdexcept>
#include <cctype>

namespace {

 /**
  *      .
  */
 int getval(const char*& iptr)
 {
  int ret=0;
  do ret=ret*10 + *iptr-'0';
     while (std::isdigit(*++iptr));

  return ret;
 }

}

c_form_private::Formatter::Formatter(const char* form, int arg1, int arg2) :
  newFlags(fmtflags()), width(0), prec(0), fill(0)
{
 const char* iptr=form;  //    

 if (*iptr=='-') {  //  
    newFlags|=ios::left;
    iptr++;
 }
 else if (*iptr=='0') {  //  '0'   !left
         fill='0';
         iptr++;
      }

 if (*iptr=='*') {  //  ,  
    width=arg1;
    iptr++;

    arg1=arg2;  //   
 }
 else if (std::isdigit(*iptr)) width=getval(iptr);

 if (*iptr=='.') {  //  
    if (*++iptr=='*') {
       prec=arg1;
       iptr++;
    }
    else if (std::isdigit(*iptr)) prec=getval(iptr);
         else throw std::invalid_argument("c_form");
 }

 switch (*iptr++) {
        case   0: return;  //   
        case 'e': newFlags|=ios::scientific; break;
        case 'f': newFlags|=ios::fixed;      break;
        case 'g':                            break;
        case 'o': newFlags|=ios::oct;        break;
        case 'x': newFlags|=ios::hex;        break;
        default: throw std::invalid_argument("c_form");
 }

 if (*iptr) throw std::invalid_argument("c_form");
}

void c_form_private::Formatter::setFormatting(ostream& os)
{
 oldFlags=os.flags();
 //  floatfield    
 os.flags((oldFlags & ~ios::floatfield) | newFlags);

 if (width) os.width(width);
 if (fill)  fill=os.fill(fill);
 if (prec)  prec=os.precision(prec);
}

void c_form_private::Formatter::restoreFormatting(ostream& os)
{
 os.flags(oldFlags);

 if (fill) os.fill(fill);
 if (prec) os.precision(prec);
}
: c_form<>() c_form_private::Helper<>, ostream.

, c_form<>() , .. - c_form<>, :

cout<<c_form<int>(day,"02");
, , . . , , Formatter, Helper<>, ( ) .

, c_form . , , () .


.711: 21.6.2.

readsome() , ...

.. readsome() , :

27.6.1.3 [lib.istream.unformatted]

streamsize readsome(char_type* s, streamsize n);
  1. : !good() setstate(failbit), . , s. rdbuf()->in_avail() == -1, setstate(eofbit) ( ios_base::failure (27.4.4.3)) ;
    • rdbuf()->in_avail() == 0,
    • rdbuf()->in_avail() > 0, min(rdbuf()->in_avail(),n))
  2. : .

.773: 23.4.3.1. 1:

, -- , , .

, , .. . , Circle Ellipse , is-a: . , .

, , : a b. . , , .. . -- , , . , , .. , .

? , , .. . , (, , b -- ). , , (), .. , , .


.879: .5.

" , ".

.. C++ , . :

T(*e)(int(3)); T* e(int(3)); , int , : .
T(f)[4]; T f[4];
T(a); T a;
T(a)=m; T a=m;
T(*b)(); .
T(x),y,z=7; T x,y,z=7;


.931: B.13.2.

:
template<class C> class Basic_ops {  //    
	friend bool operator==<>(const C&, const C&);  //  
	friend bool operator!=<>(const C&, const C&);
	// ...
};
(<>) , - ( ).

10 .

<>? operator==() , .. operator==()-. :

14.5.3. [temp.friend]

  1. - -, -, ( ) . - :
    • template-id, -,
    • qualified-id , ,
    • qualified-id -, ,
    • unqualified-id, ( ) ( ) .
    :
    template<class T> class task;
    template<class T> task<T>* preempt(task<T>*);
    
    template<class T> class task {
    	//  ...
    	friend void next_time();
    	friend void process(task<T>*);
    	friend task<T>* preempt<T>(task<T>*);
    	template<class C> friend int func(C);
    
    	friend class task<int>;
    	template<class P> friend class frd;
    	//  ...
    };
    next_time - task; .. process template-arguments, - task - process -; .. preempt template-argument <T>, - task - preempt; , , - task - func. , - task - task<int>, - frd.

.935: B.13.6. template

.

- - . , - -? :

template <class T> void get_new3();  // (1)

template <class Allocator>
void f(Allocator& m)
{
 int* p1=         m.template get_new1<int>( );
 int* p2=Allocator::template get_new2<int>(m);
 int* p3=                    get_new3<int>(m);
}

struct Alloc {
       template <class T>
       T* get_new1() { return 0; }

       template <class T>
       static T* get_new2(Alloc&) { return 0; }

       template <class T>
       friend T* get_new3(Alloc&) { return 0; }
};

int main()
{
 Alloc a;
 f(a);
}
:
  1. get_new1 --- -, template. , f Allocator , -- () (m.get_new1) < int...
  2. get_new2 -- -, f, template .
  3. get_new3 -- Alloc, . , f Alloc ( , get_new1 get_new2). f , , get_new3 f -. f, (1) get_new3 -- Alloc, ( !) - get_new3. , f --
    p3=get_new3<int>(m);
    , -. , (1) get_new3 . , ( ) get_new3, f.
, - , .. C++ , , :
p3=template get_new3<int>(m);
, , template C++.

.

? ? ? , . , :

  1. , .
  2. .
: . -- .

, , -- ! ? , ; . ? .

, "" , .. . -- "". , . , , . , -- . , -- . , , ( : (!) - UPDATE STATISTICS; , SQL- . " " ).

, . , . - . "" SQL- , , , . "" .

, .. ( , ). ""- ( , . , ) " " (, , int, ). -- .

, . ? . , , , :

, , . , , ( , ) (, ; , ; , ; -- blue death screen, system trap .., .. ).

, ( : a+a 2*a, register int i; ..), ( , " " ). .

( O(N*N), O(N*log(N)) O(N*M) ). ! , , , . , "" !

, . . , , -. , . , , sin(x), ( 360 int ). "" -- switch . , ( O(1)) ( O(log(N))) -- O(N), switch. switch .

. C++.

, , - C++ , . , " ", .. () C++, .

C++ C . .. , , , . ( _fastcall), , . :

void f1(int arg)
{
 Var+=arg;
}

void _fastcall f2(int arg)
{
 Var+=arg;
}
f1() 50% . , . .

-- . ? , -- , , 90% ! , , , . .

( ), , . , . - ? f() file1.cpp g() file2.cpp, , , file2.cpp . , , file2.cpp - g2(), g() - ; -... , , .

Paul Hsieh "Programming Optimization". , "", , , Steve Heller "Optimizing C++".


C++ ! , ? : , .

, , . , C++, .

, ?

  1. . , _VAL_, :
    #define _VAL_(var) #var "=" << var << " "
    , ( ) , . .
  2. -- . _ADD_. :
    	cout<<_ADD_(" ");
    -
      <file.cpp:34>
    ,
    	cout<<" " _ADD_("") "\n";
    , _ADD_ .
    	char* _ADD_(char*);
    , . , cout , .

    _ADD_:

    #define _ADD_tmp_tmp_(str,arg) str " <" __FILE__ ":" #arg ">"
    #define _ADD_tmp_(str,arg) _ADD_tmp_tmp_(str,arg)
    #define _ADD_(str) _ADD_tmp_(str,__LINE__)
    ? , __LINE__ __FILE__ , . , , :
    #define _ADD_(str) str " <" __FILE__ ":" #__LINE__ ">"
    .. # . __LINE__ ,
    #define _ADD_tmp_(str,arg) str " <" __FILE__ ":" #arg ">"
    #define _ADD_(str) _ADD_tmp_(str,__LINE__)
    : _ADD_(" ")
    "  <file.cpp:__LINE__>"
    . , : _ADD_(" ")
    _ADD_tmp_(" ",__LINE__)
    _ADD_tmp_tmp_(" ",34)
    " " " <" "file.cpp" ":" "34" ">"
    "  <file.cpp:34>"
  3. . , "" . , SQL- DB::Query
    void DB::Query::Statement(const char *);
    , " " somefield:
    #define FieldOK 7
    // ...
    DB::Int tmp(FieldOK);
    q.Statement(" SELECT * "
                " FROM sometable "
                " WHERE somefield=? "
    );
    q.SetParam(), tmp;
    . FieldOK ? :
    #define FieldOK 7
    // ...
    #define FieldOK_CHAR "7"
    // ...
    q.Statement(" SELECT * "
                " FROM sometable "
                " WHERE somefield=" FieldOK_CHAR
    );
    .
    #define FieldOK 7
    // ...
    q.Statement(" SELECT * "
                " FROM sometable "
                " WHERE somefield=" _GETSTR_(FieldOK)
    );
    _GETSTR_ :
    #define _GETSTR_(arg) #arg
    , C++
    const int FieldOK=7;
    enum { FieldOK=7 };
    _GETSTR_ .
  4. . SQL-. , . :
    struct Table1 {  //   
           DB::Date  Field1;
           DB::Int   Field2;
           DB::Short Field3;
    };
    
    void f()
    {
     Table1 tbl;
     DB::Query q;
     q.Statement(" SELECT Field1, Field2, Field3 "
                 " FROM Table1 "
     );
     q.BindCol(), tbl.Field1, tbl.Field2, tbl.Field3;
     // ...
    }
    . , ? -- ! :
    #define TABLE1_FLD      Field1, Field2, Field3
    #define TABLE1_FLD_CHAR "Field1, Field2, Field3"
    
    struct Table1 {  //   
           DB::Date  Field1;
           DB::Int   Field2;
           DB::Short Field3;
    
           //  
           void BindCol(DB::Query& q) { q.BindCol(), TABLE1_FLD; }
    };
    
    void f()
    {
     Table1 tbl;
     DB::Query q;
     q.Statement(" SELECT " TABLE1_FLD_CHAR
                 " FROM Table1 "
     );
     tbl.BindCol(q);
     // ...
    }
    . , TABLE1_FLD_CHAR _GETSTR_(TABLE1_FLD), .. TABLE1_FLD . , C++ .
  5. . , . , , , , :
    q.Statement(" SELECT Field1, AccA_bal, AccA_cur, AccA_key, AccA_brn, "
                " AccA_per, Field2 "
                " FROM Table1 "
    );
    q.BindCol(), tbl.Field1, tbl.AccA.bal, tbl.AccA.cur, tbl.AccA.key,
                 tbl.AccA.brn, tbl.AccA.per, tbl.Field2;
    // ...
    , (tbl.AccA, tbl.AccB, tbl.KorA, tbl.KorB). :
    #define _SACC_(arg) #arg"_bal, "#arg"_cur, "#arg"_key, "#arg"_brn, " \
                        #arg"_per "
    #define _BACC_(arg) arg.bal, arg.cur, arg.key, arg.brn, arg.per
    
    // ...
    
    q.Statement(" SELECT Field1, " _SACC_(AccA) " , Field2 "
                " FROM Table1 "
    );
    q.BindCol(), tbl.Field1, _BACC_(tbl.AccA), tbl.Field2;
    // ...
    , .
  6. . :
    struct A {
           MyDate Date;
           int    Field2;
           short  Field3;
    };
    Date , .. DATE SQL. :
    struct TableA {
           DB::Date  xDate;
           DB::Int   xField2;
           DB::Short xField3;
    
           TableA& operator=(A&);
           void Clear();
    };
    -:
    TableA& TableA::operator=(A& a)
    {
     xDate=ToDB(a.Date);
     xField2=ToDB(a.Field2);
     xField3=ToDB(a.Field3);
    
     return *this;
    }
    
    void TableA::Clear()
    {
     xDate="";
     xField2="";
     xField3="";
    }
    , TableA - , , ! , ? :
    TableA& TableA::operator=(A& a)
    {
    //   : ##
    #define ASS(arg) x##arg=ToDB(a.arg);
     ASS(Date);
     ASS(Field2);
     ASS(Field3);
    #undef ASS
    
     return *this;
    }
    
    void TableA::Clear()
    {
    #define CLR(arg) x##arg=""
     CLR(Date);
     CLR(Field2);
     CLR(Field3);
    #undef CLR
    }
    TableA::Clear() TableA::operator=() , , , . : A& A::operator=(TableA&).
, - C++.
Copyright © . , 2000-2004

.


Last-modified: Thu, 07 Dec 2006 05:46:12 GMT
: