본문 바로가기
IoT 디바이스 활용/C++

C++ - 객체의 동적 생성

by cooluk 2020. 10. 12.

객체의 동적 생성

  • 객체의 동적 생성

    • 객체에 대해서도 동일한 원칙 적용

    • 멤버 접근에 대한 표현이 다름

      • 포인터_변수->멤버
    • Dog *pDog = new Dog;

      pDog->age = 10;
      :
      delete pDog;


    #include <iostream>
    #include <memory>
    #include <string>
    using namespace std;
    
    class Dog
    {
    public:
        int age;
        string name;
        Dog()
        {
            cout << "Dog constructor call" << endl;
            age = 1;
            name = "puppy";
        }
        ~Dog()
        {
            cout << "Dog deconstructor call" << endl;
        }
    };
    
    int main(int argc, char const *argv[]) {
        unique_ptr<Dog> buf(new Dog); // startporinter사용, 소멸자 자동으로 호출
    //    Dog *pDog = new Dog; // Dog constructor call
    //    delete pDog; // Dog deconstructor call
       return 0;
    }

    Dog constructor call
    Dog deconstructor call



  • 포인터로 객체 멤버 접근하기
    (*pDog).getAge(); // 실제 인스턴스가 되서 .을 붙일 수 있음
    pDog->getAge(); // 포인터로 멤버 접근할 때 -> 사용
    // 둘 다 같은 표현


포인터로 객체 멤버 접근하기

#include <iostream>
#include <string>
using namespace std;

class Dog{
public:
    int age;
    string name;

    Dog(){
        age = 1;
        name = "puppy";
    }    
    ~Dog(){ }

    int getAge() { return age;}
    void setAge(int a) { age = a; } 
};

int main(int argc, char const *argv[]) {
   Dog *pDog = new Dog;

   cout << "puppy's age : " << pDog->getAge() << endl;
    // 화살표를 이용하여 객체 멤버 접근

   pDog->setAge(3);
   cout << "puppy's age : " << pDog->getAge() << endl;

   delete pDog;
   return 0;
}

puppy's age : 1
puppy's age : 3



멤버도 동적 생성하기

#include <iostream>
#include <string>
using namespace std;

class Dog{
private:
    int *pAge; // 멤버변수
    int *pWeight;
public:
    Dog(){
        pAge = new int{1};
        pWeight = new int{10};
    }
    ~Dog(){
       // 만약 pAge와 pWeight delete를 하지 않게되면 Dog가 가리키는 객체만
       // 사라지게 되어 pAge와 pWeight 의 저장공간은 남게되어 garbage가 생김
        delete pAge;
        delete pWeight; 
    }
    int getAge(){ return *pAge; }
    void setAge(int a) { *pAge = a; }
    int getWeight(){ return *pWeight; }
    void setWeight(int w) { *pWeight = w; }
};

int main(int argc, char const *argv[]) {
   Dog *pDog = new Dog;
   cout << sizeof(pDog) << endl; // pDog포인터 변수의 크기, 8출력
   cout << sizeof(*pDog) << endl; // pDog포인트하는 인스턴스의 크기, 16출력

   cout << "puppy's age : " << pDog->getAge() << endl;

   pDog->setAge(3);
   cout << "puppy's age : " << pDog->getAge() << endl;

   delete pDog;   
   return 0;
}

8
16
puppy's age : 1
puppy's age : 3


포인터 변수의 크기는 상관없이 8바이트
Dog인스턴스의크기는 *pAge, *pWeight 두개의 포인터 변수를 갖고 있어 16바이트



  • this 포인터

    c++에서 변수 접근 방법 : 지역변수 - > 멤버변수 -> 전역변수 -> 에러

    • 모든 객체가 가지는 멤버 변수
    • 자신(인스턴스)에 대한 포인터 변수
    • 멤버 변수와 매개 변수의 이름이 같은 경우 멤버 변수를 지칭하기 위해 사용

    this는 포인터이기 때문에 .이 아니라 화살표(->)를 사용해야 함

    #include <iostream>
    #include <string>
    using namespace std;
    
    class Rectangle{
    private:
        int length;
        int width;
    public:
        // Rectangle(int length=30, int width=40){
        //     this->length = length;
        //     this->width = width;
        // }    
    
        // 멤버 초기화 리스트로 초기화하기
        Rectangle(int length=30, int width=40) : length(length), width(width){
        } // this를 쓰지 않아도 규칙이 있어 변수를 받아옴
          //length(length) : 괄호 밖 -> 멤버변수, 괄호 안 -> 규칙상 지역변수
        ~Rectangle() {}
        void setLength(int length){
            this->length = length;
        }
        int getLength(){
            return this->length;
        }
        void setWidth(int width){
            this->width = width;
        }
        int getWidth(){
            return this->width;
        }
    };
    
    int main(int argc, char const *argv[]) {
       Rectangle rect;
    
       cout << "rectangle's width : " << rect.getWidth() << endl;
       cout << "rectangle's length : " << rect.getLength() << endl;
    
       rect.setLength(50);
       rect.setWidth(60);
    
       cout << "rectangle's width : " << rect.getWidth() << endl;
       cout << "rectangle's length : " << rect.getLength() << endl;
       return 0;
    }

    rectangle's width : 40
    rectangle's length : 30
    rectangle's width : 60
    rectangle's length : 50



  • const 포인터

    • const int *p1; // 상수에 대한 포인터, 값이 상수임, 값을 바꿀 수 없음
    • int * const p2; // 포인터가 상수임. 다른 주소로 바꿀 수 없음
    • const int * const p3; // 포인터와 값 모두 상수
    #include <iostream>
    using namespace std;
    
    int main(int argc, char const *argv[]) {
        // 프로그램에서 사용된 literal데이터 (Hello, c++등)는 전역영역에 저장, 상수이다.
       char test[] = "Hello"; // 문자열 배열(6바이트->마지막 \0 포함, Hello를 복사해와서), 지역변수, stack에 할당, literal데이터를 가져와 복사를 한다.
       char *pstr = "C++"; // 문자열 포인터(8바이트), 지역변수, stack에 할당, 주소값 대입 후 c++이 있는 전역영역을 가리킴
       string str = "World"; // string 객체(32바이트, 실제 데이터와 상관없이 string은 32바이트이다), stack에 할당, string은 불변객체가 아님, insert, remove를 통해 늘릴 수도있고 줄일 수도있다. 내부적으로 동적 데이터를 운영
    
        // *pstr = 'P'; // 에러남
       cout << test << endl;
       cout << pstr << endl;
       cout << str << endl;
    
       return 0;
    }

    Hello
    C++
    World




정리

image-20200909143806785

  • print(test);

    • strint t = test
    • t에 test를 대입 받아 Hello를 복사 한 후 Heap에 메모리를 할당한다. 함수가 끝나면 소멸자로 인해 메모리가 사라진다.
  • print(pstr);

    • string t = pstr

    • t에 pstr을 대입 받아 c++을 복사 한 후 Heap에 메모리를 할당 된다. 함수가 끝나면 소멸자로 인해 메모리가 사라진다.

  • print(str);

    • string t = str;

    • pstr과 같이 t의 영역공간에 str을 받아 가리키고있는 world를 복사한다. 함수가 끝나면 소멸자로 인해 메모리가 사라진다.

      image-20200909144352134

void print(char t[]); 
void print(const char *t); // *t = 'A'; <- 이런식 사용안됨
// 두개의 표현은 상수만 받아올 수 있다, 즉 string은 받아올 수 없다.
print(str.c_str); //.c_str을 사용하면 string의 값이 들어있는 주소값을 받아올 수 있어 사용 가능하다.
// const char * 리턴, 읽을 순 있지만 수정은 불가능하다

image-20200909145128641

'IoT 디바이스 활용 > C++' 카테고리의 다른 글

C++ - 상속  (0) 2020.10.12
C++ - 복사생성자와 정적멤버  (0) 2020.10.12
C++ - 동적 할당 메모리  (0) 2020.10.12
C++ - 포인터  (0) 2020.10.12
C++ - 객체 배열, 벡터  (0) 2020.10.12

댓글