본문 바로가기

C++

[C++] 포인터 - 얕은복사/깊은복사(샘플3), 생성자, 소멸자

 

 

#include <iostream>

class string
{
    char *str;
    int len;

public:
    string(char c, int n);     // 문자 c 가 n 개 있는 문자열로 정의
    string(const char *s);     // 일반 생성자
    string(const string &s);   // 복사 생성자
    ~string();                 // 소멸자

    void add_string(const string &s);  // str 뒤에 s 를 붙인다.
    void copy_string(const string &s); // str 에 s 를 복사한다.
    int strlen();
    // int GetLen() { return len; }
    // char *GetStr() { return str; }
    void show();
};

int string::strlen()
{
    int len = 0;
    while (str[len] != '\0')
    {
        len++;
    }
    return len;
}

string::string(char c, int n)
{
    std::cout << "생성자(string(char c, int n))" << std::endl;
    str = new char[n];
    for (len = 0; len < n; len++)
    {
        str[len] = c;
    }
    str[len] = '\0';
}

string::string(const char *s)
{
    std::cout << "생성자(string(const char *s))" << std::endl;
    len = 0;
    while (s[len])
    {
        len++;
    }

    str = new char[len + 1];
    memset(str, 0x00, sizeof(char) * (len + 1));
    strcpy(str, s);
}

string::string(const string &s)
{
    std::cout << "생성자(복사생성자)" << std::endl;
    str = new char[s.len + 1];
    // str = s.str;
    memset(str, 0x00, sizeof(char) * (s.len + 1));
    strcpy(str, s.str);
    len = s.len;
}

string::~string()
{
    std::cout << "[" << str << "]"
              << " - destructed" << std::endl;
    if (str)
        delete str;
}

void string::add_string(const string &s)
{
    char *temp = new char[len + s.len + 1];
    // 메모리를 강제 초기화, 가끔 쓰레기 데이터가 생기는 경우 있음
    // 전체를 널로 초기화 하므로 배열/포인터 끝을 '\0' 처리할 필요없음
    memset(temp, 0x00, sizeof(char) * (len + s.len + 1));

    printf("add_string() - my len: [%d], s.len:[%d]\n", len, s.len);
    // strcat을 직접 구현함
    for (int i = 0; i < len; i++)
    {
        temp[i] = str[i];
    }
    for (int i = 0; i < s.len; i++)
    {
        temp[len + i] = s.str[i];
    }

    len += s.len;
    delete[] str;
    str = temp;
}

void string::copy_string(const string &s)
{
    char *temp = new char[s.len + 1];
    // 메모리를 강제 초기화, 가끔 쓰레기 데이터가 생기는 경우 있음
    // 전체를 널로 초기화 하므로 배열/포인터 끝을 '\0' 처리할 필요없음
    memset(temp, 0x00, sizeof(char) * (s.len + 1));

    printf("copy_string() - my len: [%d], s.len:[%d]\n", len, s.len);
    // strcpy를 직접 구현함
    for (int i = 0; i < s.len; i++)
    {
        temp[i] = s.str[i];
    }
    len = s.len;
    delete[] str;
    str = temp;
}

void string::show()
{
    printf("str(s):  [%s]\n", str);
    // printf("str(s+1): [%s]\n", str + sizeof(char));
    printf("len: [%d]\n", len);
    printf("str' address: %p\n", str);
    // printf("len' address: %p\n", &len);
    std::cout << std::endl;
}

int main()
{
    string *s1 = new string('a', 10);
    s1->show();

    string *s2 = new string("Hello ");
    s2->show();

    string *s3 = new string(*s2);
    s3->show();

    string *s4 = s2;
    s4->show();

    string *s5 = new string("World");
    s5->show();

    std::cout << "------------------------" << std::endl;
    s2->add_string(*s5);
    s2->show();
    s4->show();
    std::cout << "------------------------" << std::endl;

    s4->copy_string(*s5);
    s4->show();

	// 소멸자가 자동실행되지 않아서 강제 실행함
    // s1->~string();
    // s2->~string();
    // s3->~string();
    // // s4->~string(); // 얕은복사이므로 소멸자 호출하면 안된다.
    // s5->~string();

    return 0;
}

 

 

 

 

 

 

 

참고자료 : "모두의 코드" 사이트.