헤더파일

컨테이너 - 3 본문

C++

컨테이너 - 3

헤더파일 2018. 4. 12. 12:13

int main()

{

Model a(1234);

vector<Model> v;


v.push_back(a);

}


어떤 메모리에 이름을 붙였다는건 컴파일러에게 나 여기 읽고 쓸거니까 없애지마라고 명령한 것이다.



int main()

{

vector<Model> v;


v.push_back(Model{1234});

}



이렇게 이름 없는 객체를 넣으면 컴파일러가 판단해서 없애고 이동생성자를 부른다.

더 정확하게 쓰면 v.emplace_back(1234) 을 써서 알아서 자료형도 유추해서 넣도록 한다.

벡터는 뒤쪽에 데이터를 삽입하는 게 좋다.


전통적인 qsort로 벡터 비교.


//벡터에 플레이어 1000명의 정보를 만들어 넣어보자

//플레이어는 id,score1,score2 

class Player

{

private:

string id; //플레이어 이름

int score1; //1번경기 최고점수

int score2; //2번 경기 최고점수

short rank1; //1번경기 등수

short rank2; //2번경기 등수

public:

Player(string s, int n1, int n2) : id(s), score1(n1), score2(n2) {}

void show() const {

cout << id << ", 점수1: " << score1 << "(" << rank1 << ")등, 점수2: "

<< score2 << "(" << rank2 << ")등," << endl;

}

int getscore1() const { return score1; }

int getscore2() const { return score2; }


};

int cnt{ 0 };

int main()

{

vector<Player> v;

//v.emplace_back(1234); //vetor을 사용하는 가장 좋은 방법

random_device rd;

default_random_engine dre(rd());

uniform_real_distribution<> uidN1(0, 40000000);

uniform_real_distribution<> uidN2(0, 300000000);


v.reserve(1000);

for (int i = 0; i < 1000; ++i)

{

v.emplace_back(to_string(i + 1) + string(" 선수"), uidN1(dre), uidN2(dre));

}

//1번 경기점수 기준 내림차순으로 정렬


qsort(v.data(), v.size(), sizeof(Player), [](const void* a, const void* b)

{

cnt++;

return ((Player*)b)->getscore1() - ((Player*)a)->getscore1();

});

cout << "qusort의 비교횟수 " << cnt << endl;



}


비교횟수는 10000번 정도이다.


stl의 sort함수로 정렬


sort(v.begin(), v.end(), [&cnt](const Player& a, const Player& b) {

++cnt;

return a.getscore1() < b.getscore1();

});


비교횟수는 15000번이지만 qsort보다 빠르다.

이유는 c++ 템플릿이 특정 자료형에 맞는 최적화된 코드를 만들어주기 때문이다.

하지만 이 차이는 sort할 비교대상이 10000번 정도가 아니라 훨씬 많아야 합니다. 같은 자릿수의 시간차이는 의미가 없습니다. 만약 전역함수를 쓰지 않고 함수객체를 전달한다면 람다나 함수객체 모두 인라인화 되기때문에 속도가 비슷합니다.


함수객체->클래스로 묶은 후 오퍼레이터 오버로딩 하는 방법.


vector를 이용한 바이너리 파일입출력


const int MAX_PLAYER =100;

vector<Data> v;

......

//사이즈 만큼 v에 값을 집어넣는다.


Data라는 사용자 정의 클래스가 있고 vector의 크기가 MAX_PLAYER라는 상수로 정해져 있을 때 vector의 파일 출력은 이렇게 작성한다.



ofstream out("output.txt", ios::binary);


out.write((char*)v.data(), vsize() * sizeof(Data));


v.data() 는 벡터의 첫번째 주소값을 넘겨주는 함수다. 시작번지부터 v.size() * sizeof(Data) 까지의 메모리를 파일에 쓰게 되면 벡터의 모든 값을 파일에 넣게 된다.


ifstream in("output.txt", ios::binary);


if (in)

{

v.resize(MAX_PLAYER);

in.read((char*)v.data(), sizeof(Data) * MAX_PLAYER);

}


입력 할때는 파일 출력할 때 썼던 자료형과 같은 벡터를 선언하고 resize로 출력할 때의 크기만큼 크기를 늘린다. 그 다음 write할때와 똑같이 벡터의 시작번지부터 끝까지 설정하면 텍스트 파일안에 바이너리로 저장된 데이터가 벡터안에 들어오게 된다. 주의 할 점이 하나있는데 클래스안에 맴버변수로 string이 있으면 작동하지 않기 때문에 char 배열로 크기가 고정된 멤버변수로 선언해줘야 한다.





'C++' 카테고리의 다른 글

연관 컨테이너  (0) 2018.04.30
노말분포 & 시퀀스 컨테이너  (0) 2018.04.16
컨테이너 - 2  (0) 2018.04.09
컨테이너 -1  (0) 2018.04.05
스마트 포인터  (0) 2018.04.05
Comments