2016-12-25 1 views
0
#include <iostream> 
#include <cstring> 
#include <vector> 

using namespace std; 

class items{ 
    char * name; 
public: 
    items(const char * str){ 
     int len = strlen(str); 
     this->name = new char [len]; 
     strcpy(this->name,str); 
     cout << "Default ctor " << this->name << " \[email protected]" << (this) << endl; 
    } 

    items(const items& obj){ 
     int len = strlen(obj.name); 
     this->name = new char [len]; 
     strcpy(name,obj.name); 
     cout << "Copy ctor " << this->name << " \[email protected]" << this << endl; 
    } 

    ~items(){ 
     cout << "dtor \t" << this->name << "\[email protected]" << this << endl; 
     delete [] name; 
    } 

    const char * getName() const{ 
     return this->name; 
    } 
}; 

ostream& operator<<(ostream& stream, const items& obj){ 
    stream << obj.getName(); 
    return stream; 
} 

int main(int argc, char ** argv){ 
    items Ruler("Ruler"), Pencil("Pencil"), Book("Book"), Notebook("Notebook"), Sharpener("Sharpener"); 


    vector<items> school; 
    school.push_back(Ruler); 
    school.push_back(Pencil); 
    school.push_back(Book); 

    return 0; 
} 

나는 기괴한 결과가 있습니다. 현장 뒤에서 일어나는 일을 설명해 주시겠습니까? 결과 :너무 많은 복사본을 찾을 수 없습니다.

Default ctor Ruler @0x62ff1c 
Default ctor Pencil  @0x62ff18 
Default ctor Book @0x62ff14 
Default ctor Notebook @0x62ff10 
Default ctor Sharpener @0x62ff0c 
Copy ctor Ruler  @0x9cd1d0 
Copy ctor Pencil @0x9cd504 
Copy ctor Ruler  @0x9cd500 
dtor Ruler @0x9cd1d0 
Copy ctor Book @0x9c0510 
Copy ctor Ruler  @0x9c0508 
Copy ctor Pencil @0x9c050c 
dtor Ruler @0x9cd500 
dtor Pencil @0x9cd504 
dtor Ruler @0x9c0508 
dtor Pencil @0x9c050c 
dtor Book @0x9c0510 
dtor Sharpener @0x62ff0c 
dtor Notebook @0x62ff10 
dtor Book @0x62ff14 
dtor Pencil @0x62ff18 
dtor Ruler @0x62ff1c 

기본 구성 후에 어떤 현상이 발생합니까? 왜이 통치자가 너무 많은 복사본을 만들어 파괴합니까? 여기에 어떤 문제가 있습니까?

+2

"기본 생성자"가 기본 생성자가 아니 어서 오해의 소지가 있습니다. – Quentin

+0

예상했던 사본을 설명하면 오해에 대해 설명 할 수 있습니다. – user2357112

+0

벡터에서 아이템을 푸시 할 때 임시 복사본이 만들어 짐 – FamZ

답변

1

기본적으로 어떤 일이 발생하는지는 벡터가 꽉 차고 요소를 밀면 벡터의 크기를 조정해야한다는 것입니다. 따라서 Ruler을 벡터에 푸시하면 크기가 sizeof(items) 인 배열이 생성되고 데이터가 복사됩니다 (Ruler에 대한 첫 번째 복사본 생성자 호출). 그런 다음 벡터에 Pencil (첫 번째 복사 생성자 호출 Pencil)을 밀고 있지만 벡터에 메모리가 부족하여 새 배열에 이전 크기 인 2 * sizeof(items)의 두 배가 할당되고 이전 배열이 새 배열에 복사됩니다 (두 번째 복사 생성자 호출에 대한 호출 Ruler) 및 이전 배열이 소멸됩니다 (이전 배열에서 Ruler에 대한 첫 번째 소멸자가 호출 됨) ...

1

std :: vector는 자체 메모리를 관리합니다. 즉, std :: vector는 객체의 복사본 만 저장합니다. 즉, 객체에 의미있는 복사본 생성자 (및 할당 연산자가 있어야하지만 또 다른 문제)가 있어야합니다.

벡터의 소멸자가 호출 될 때 벡터에 의해 보유 된 메모리가 해제됩니다. std :: vector는 (erase, pop_back, clear 또는 벡터의 소멸자를 통해) 제거 될 때 객체의 소멸자를 호출합니다.

2

"기본 생성자"는 인수를 취하므로 기본 생성자가 아닙니다. C++의 의미 : 기본 생성자는 아무런 인자없이 호출 될 수 있습니다. 이 순서를 보인다 귀하의 질문에 대하여

따라서이다 : 처음

  1. 모든 구성받을 객체.
  2. 벡터에 Ruler 개체의 복사본이 삽입되어 있습니다.
  3. Pencil이 삽입되면이 개체가 처음 복사되지만 Pencil 개체가 새로 할당 된 위치에 복사 된 다음 Ruler 개체가 복사되어 원래 공간이 삭제됩니다.
  4. Book을 삽입하면 Book이 새 위치로 복사 된 다음 RulerPencil도 복사됩니다.
  5. 마지막으로 모든 개체가 파괴됩니다.

시퀀스는std::vector 보통처럼 작동하지 않는다는 점에서 다소 혼란 : 정상적으로 오른쪽 하나 개 이상의 요소를 수용 할 수있는 시작의 작은 배열을 만든다. 사용 된 구현은 capacity()으로 시작한 다음 거기에서 용량을 두 배로 늘리는 것 같습니다. school.push_back()에 대한 호출간에 school.capacity()을 확인하여이 동작을 확인할 수 있습니다. capacity()이 증가 할 때마다 기본 배열이 증가합니다.

메모리를 할당한다고 가정하면 복사본을 수용하기 위해 새로운 배열을 할당하는 대신 저장된 메모리를 전송하는 이동 생성자를 고려해야 할 수도 있습니다. 원래는 delete입니다. 이동 생성자는 다음과 같습니다.

items::items(items&& other) 
    : name(other.name) { 
    this->name = nullptr; 
} 
관련 문제