헤더파일
컨테이너 - 3 본문
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 배열로 크기가 고정된 멤버변수로 선언해줘야 한다.