6교시

//
동적메모리할당
 

// 1. 왜동적메모리할당을사용하는가?

//    주로실행시간결정된값으로메모리를할당하기위해.


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

// 배열의크기에대해서


void
foo( const int c )

{

        int ar[c];        // error. 실행해봐야알수있다.(컴파일시간에결정!!)

}

 

int main()

{

        const int x = 10;

        int ar[x];       // ok.

 

        const int sz[3] = { 1, 2, 3 };

        int br[ sz[1] ]; 
       
// error.
배열의크기는상수가아니라

        // 컴파일시간에크기를알아야하는것이다.

        // sz[1] => *(sz+1)

}

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

void main()

{

        //C++

        int* p1 = new int;

        int* p2 = new int[10];

 

        delete p1;

        delete[] p2;

 

        int* p3 = new int(3);  // 3으로초기화

 

        // 2차원배열의주소는1차원배열포인터로가르키면된다.

        int(*p4)[10] = new int[10][10];              // 2차원배열형태로.

       

        int* p6 = new int;

        free(p6);              // undefined

 

        int* p7 = new int[10];

        delete p7;             // undefined

 

        int n;

        cout << "학생수를넣어주세요. >>";

        cin >> n;

 

        // 학생수만큼의메모리를할당하고싶다.   

        //int jumsu[n]; 
       
//
배열의크기는변수가될수없다. 상수이어야한다.

 

        int* jumsu = (int*)malloc( sizeof(int)*n );         

}

Tag |

5교시

//
리턴값과레퍼런스이야기

 

// 값을리턴하는함수

// 1) bulit in type 의값을리턴( ex. int foo() )

//      => 리턴값은상수취급된다.

// 2) user type의값을리턴( ex. Point foo() )

//      => 임시객체를리턴한다.( 일부컴파일러는임시객체를상수취급하기도한다.)

int x = 10;

 

int& foo()

{

        return x;

}

 

void main()

{

//      int s = foo();        // 값을리턴하면10 = 30의의미를가진다.

        foo() = 30;           // &을리턴하면된다.

                               

 

         cout << x << endl;

}

 

//================================================

// 1. 함수가레퍼런스를리턴하는이유.

//    (1) built in type의레퍼런스( int& foo() )

//             => "함수호출() = "의표현을가능하게하기위해

//             => 함수호출이lvalue에놓이기위해.

 

//    (2) user type의레퍼런스-> 임시객체의생성을막기위해사용.

//             ex) Point& foo()

 

struct Point

{

        int x;

        int y;

};

Point p = { 1, 2 };

 

Point& foo()

{

        return p;

}

 

void main()

{

        foo().x = 10;          // user type의리턴값은상수가아니다.

 

        cout << p.x << endl;

}

Tag |

7.24(화) C++기초문법 - reference

from Study/C++ 2007/07/24 17:14 view 22275

4교시

//
레퍼런스문법총정리

// 1. 개념: 기존메모리에대한별명.

int main()

{

        int  n = 10;

        int* p = &n;

        int& r = n;            //

 

        r = 20;

 

        cout << n << endl;     // 20

 

        int& r2;               // ? Error. 반드시초기화되어야한다.

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

        int*& rp = p;  // ok. 포인터의별명

        int&* pr = r;  // 별명의주소?  error

}


 

// 2. 원리: 내부적으로대부분의컴파일러는포인터를사용한다.

//         "자동으로역참조되는포인터" 라고도부른다.

void inc1( int x )     { ++x; }

void inc2( int* p )    { ++(*p); }

void inc3( int& r ) { ++r; }

 

void main()

{

        int a = 10;

        int b = 10;

        int c = 10;

 

        inc1( a );             // 실패- call by value

        inc2( &b );            // ok. call by pointer

        inc3( c );             // ok. call by reference int &r = c;

 

        cout << a << endl;     // 10

        cout << b << endl;     // 11

        cout << c << endl;     // 11

}


 

// 3. 함수호출과레퍼런스

 

// 인자값을변경하는함수-> 포인터가좀더좋다. ( 명확하다. )

// 인자값이바뀌지않은함수

// 1) bulit in type => const T&가오히려나쁘다.(4byte사용, 레지스터사용못함.)
//                     call by value
를사용.

// 2) user type     => const T&


struct AAA

{

        int data[10000000];   // 1M라고가정.

};

 

void foo( const AAA& a )   // call by value :  값을 변경하지 않을것 이다.

{                          // 단점: 메모리 사용량이 2개가 된다.

        a = 20;            // const& : 메모리 사용량을 줄이고 값을 변경하지 않게 한다.

}

 

void main()

{

        AAA x = 10;

 

        foo ( x );

       

        cout << x << endl;

}


 

Tag |

7.24(화) C++ 기초문법 - namespace

from Study/C++ 2007/07/24 16:52 view 25100

3교시

// Namespace
문법에관해서

// 1. 개념

// 프로그램을논리적인구조로구별하기위한문법

// 아울러이름충돌을막을수있다.

// 2. 함수접근방법

//    1. 완전한이름사용

//    2. using 선언(Declaration 사용)

//    3. using 지시어(Directive 사용)


namespace Audio_System

{

        void foo()

        {

               cout << "Audio" << endl;

        }

}

namespace Video_System

{

        void foo()

        {

               cout << "Video" << endl;

        }

}

void main()

{

    Audio_System::foo();

    using Audio_System::foo;


   
using namespace Video_System;
    // using
지시어: namespace 에있는함수모두를이름없이접근할수있다.

 

    foo();

}


// 3. 인자기반탐색( 퀴니크look up )

namespace Graphics

{

        struct Rect

        {

        };

        void Draw( Rect r )

        {

        }

}

 

void main()

{

        Graphics::Rect r;

 

        Draw( r );             // 될까? 자동으로r이속한namespace를검색한다.

        // namespace 를뒤진다.(연산자지정때유용하게사용한다.)

}

 

// 4. namespace 별명(Alias) 과 라이브러리의선택적사용

namespace MathLibray

{

        int plus( int a, int b )

        {

               return 0;

        }

}


//
라이브러리의교체가편해진다.

namespace MathLibray_Ver2

{

        int plus( int a, int b )

        {

               return 0;

        }

}


void
main()

{

        namespace Math = MathLibray_Ver2;     //별명Math로지정해준다.

        Math::plus( 1, 2 );

}



// 5. namespace 함수의외부구현- 클래스보다가벼운이름을묶어놓는공간


namespace AAA

{

        void foo();

}

void AAA::foo()

{

}


// 6. namespace 는열려있다. - 되도록이름을복잡하게만들어라!!

namespace A

{

        void foo() {}

}

 

//다른파일에서or 같은파일에서namespace를추가하게된다.(방지하기위해서는이름!!)

namespace A

{

        void goo() {}

}

 

// 7. namespace std

//#include <iostream.h>       // cout, endl 이전역공간에있다.

#include <iostream>           // cout, endl std라는이름공간에있다.

 

void main()

{

        std::cout << std::endl;

}

 

Tag |

7.24(화) C++ 기초문법 - explicit casting

from Study/C++ 2007/07/24 16:30 view 22122

2교시

// C++ explicit casting
개념

// 1. C의캐스팅은대부분성공한다. 하지만너무나위험하고, 버그가많다.

// 2. C++은용도에따라4가지의casting 연산자가제공된다.

// dynamic_cast : RTTI를위해존재.!! - 상속을알아야한다.

#include <iostream>

using namespace std;

 

int main()

{

        const int c = 10;

        int *p = (int*)&c;

       

        //int* p = static_cast<int*>(&c);
        //
당연히에러.. 말도안되는코드

        //int* p = reinterpret_cast<int*>(&c);
        //const
를벗겨낼수없다. error

        //int* p = const_cast<int*>(&c);
        // ok.
 동일type의객체에대해const속성을제거

        // , 지금처럼const 상수에는사용하지는않는다.const object에사용.


       
*p = 30;

 

        cout << c << endl << *p << endl << &c << endl << p << endl;

}

 

/*

int main()

{

        int a = 0;

        double d = 3.4;

        //int n = d; 
       
//
암시적변환가능. 하지만data의손실이발생한다.

 

        //static_cast : 위험하지않은이성적인변환만허용한다.

        static_cast : 위험하지않은이성적인변환만허용한다

 

        //double *p = (double*)&n;    // 암시적변환은불가능.

                                      // C의명시적변환은가능.

 

        // 결국template 함수의인자를명시적으로지정하고있는모양이다.

        //double* p = static_cast<double*>(&n);      // 허용해줄까? 에러!!

       
double* p = reinterpret_cast<double*>(&n);
        // ok..
대부분성공, C캐스팅과비슷.


       
*p = 100;

}

*/

결론 : static_cast를 사용하여 형변환을 하자!!!

Tag |

7.24(화) C++ 기초문법 - inline

from Study/C++ 2007/07/24 15:41 view 24531

1 교시

1. 함수호출의원리

// 스택을사용하기때문에약간의오버헤드가발생한다.
int square( int a )
{
    return a * a;
}

// C의해결책- 매크로함수- 하지만버그가너무많다.(특히++연산자같은경우)
#define square( x )    ((x)*(x))

// C++의해결책- inline 함수
inline int square( int x )
{
    return x * x;
}

int main()
{
    int n = square(3);     // push 3 인자를스택에넣고 
                                       // call square 함수를호출한다.
    cout << n << endl;
}

2. inline 함수의정확한개념: 호출시해당함수의기계어코드를치환

int square1( int x )
{
    return x * x;
}

inline
int square2( int x )
{
    return x * x;
}

void
main()
{
    int x = 3;
    int a = square1( x );
    int b = square2( x );

    cout << a << ", " << b << endl;

}

inline 치환을 확인하고 싶을 !

cl. acpp /Fas 로 컴파일 하면 a.asm 어셈블리 코드가 생성된다.
inline 치환을 하고 싶다면 /Ob1 이라는 옵션을 추가하면 된다.

inline 은 컴파일 시간에 결정된다. ( 파일단위로 컴파일 하게 된다. )
inline 은 반드시 호출하는 곳과 같은 곳에 있어야 한다.

3. inline 함수와화일크기 
     1. 일반적으로는 커진다.
     2. 하지만 작은 크기의 함수는 오히려 작아진다.

4. inline
과성능. 
     1. 작은
함수는 분명히 빨라진다.(파일크기도 줄어드므로 캐시에 올라올 유리)
       2.
함수는 캐시 적중률(cache hit) 떨어뜨려서 오히려 도가 줄어든다.

5,
inline 함수와헤더파일 ( internal linkage )
       1. inline 함수는 호출하는 파일과 동일 컴파일 단위에 있어야 한다.
     2. 그래서, 헤더 파일에 만들어서 include 해서 사용하는 것이 기본이다.

6. 함수
포인터와 inline
     1. 결국
인라인 함수는 만들때가 아니라 호출할 적용되는 문법이다.

inline void foo ()
{
    cout << "1" << endl;
}

void main()
{
    foo();    // ok. inline 치환된다.     

    void (*f)() = foo;     

    f();    // inline 치환될까? 대부분의컴파일러에서inline 치환이 
            // 되지않을수있다.
}

Tag |