; } 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);

 B