2015. 12. 26. 23:03ㆍ프로그래밍/Effective STL
Source
https://github.com/ElementalKiss/Cpp/blob/master/Example/VectorAndStringUsingCAPI.cpp
서론
기존에 잘 구현되어 있는 C API를 사용하는데 vector와 string을 쓰는데 뭔가 깨림찍한게 있다.
vector - &vec[0]을 통해 포인터를 넘긴다.
string - str.c_str() 함수를 통해 문자열 포인터를 넘긴다.
begin?
begin()은 엄연히 반복자를 반환하므로 헷갈리면 안된다. 굳이 사용하겠다면 &*vec.begin() 형태로....(이건 좀 아닌듯)
string은 왜 함수를 사용하는가?
- string의 데이터 자체가 연속 메모리에 저장되도록 규정되어 있지 않다.(아닐수도 있다는 이야기)
- string의 내부 문자열 값이 널 문자열로 끝나지 않는 것도 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <iostream> #include <string> #include <vector> // simple print C functions. void doSomthingVector(int* pInts, size_t numverInts) { for (int i = 0; i < numverInts; i++) { std::cout<<"print number = "<<pInts[i]<<std::endl; } return; } void dosomthingString(const char* pString) { std::cout<<"print pString[0] = "<<pString[0]<<std::endl; } int main(int argc, const char* argv[]) { // vector example std::vector<int> intVec; const int vecReserveSize = 5; intVec.reserve(vecReserveSize); for (int i = 0; i < 4; i++) { intVec.push_back(i); } doSomthingVector(&intVec[0], intVec.size()); // error C2664: 'doSomthingVector' : cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to 'const int *' // doSomthingVector(intVec.begin(), intVec.size()); // string example std::string myString; myString = "love koko"; dosomthingString(myString.c_str()); return 0; } | cs |
const?
일단 vector, string 데이터 모두 const로 넘기면 내부 데이터를 변경할 수 없다.
- string은 c_str이 문자열 데이터의 내부에 대한 포인터를 반환하다는 보장이 없다.
- string의 경우는 유일하게 읽기만 가능한 것.
- vecotor는 const 없이 포인터를 받아서 변경할 수 있으나 요소의 개수를 바꾸려고 하면 안된다.(size값이 다르게 나온다.)
C API에서 vector나 string 수정해서 넘기는 방법
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | // fill data C function size_t fillArrayDouble(double* pArray, size_t arraySize) { for (int i = 0; i < arraySize; i++) { pArray[i] = i; } return arraySize; } size_t fillString(char* pArray, size_t arraySize) { for (int i = 0; i < arraySize; i++) { pArray[i] = 'a' + i; } return arraySize; } /////////////////////main//////////////////////// // fill double vector const int maxNumDoubles = 10; std::vector<double> vd(maxNumDoubles); vd.resize(fillArrayDouble(&vd[0], 5)); for (auto it = vd.begin(); it != vd.end(); ++it) { std::cout<<"print double = "<<*it<<std::endl; } // fill string const int maxNumChar = 255; std::vector<char> vc(maxNumChar); size_t charsWritten = fillString(&vc[0], 10); std::string newStr(vc.begin(), vc.begin()+charsWritten); std::cout<<"newStr = "<<newStr<<std::endl; | cs |
컨셉? 가정?
- C API 는 해당 자료형을 할당한 길이를 리턴한다.
- 그 길이는 프로그래머가 정의하는 max를 넘지 않는다.
- STL 컨테이너는 미리 max로 초기화하고 C API가 리턴 하는 size()로 resize()한다.
- string은 vector<char>형을 이용하여 값을 넘기고 초기화 한 후 string 객체로 복사하는 형태를 취한다.
- string 복사처럼 사용하고자 하는 STL 컨테이너에 복사하는 아이디어는 항상 모든 경우에 동일하게 적용할 수 있다.
'프로그래밍 > Effective STL' 카테고리의 다른 글
[effective STL] 항목 20 : 연관 컨테이너에 포인터 넣을 때 비교 함수자 타입을 정해주기 (1) | 2015.12.27 |
---|---|
[effective STL] 항목 18 : vector<bool> 쓰지마 (1) | 2015.12.26 |
[effective STL] 항목 17 : 용량 바꿔치지 묘수(swap) (0) | 2015.12.26 |
[effective STL] 항목 15 : string은 여러 가지 방식으로 구현되어 있다. (0) | 2015.12.17 |
[effective STL] 항목 14 : 재할당 방지 reserve (0) | 2015.12.17 |
[effective STL] 항목 13 : 동적으로 할당된 배열보다는 vector와 string이 낫다. (1) | 2015.10.02 |
[effective STL] 항목 10 : 할당자(allocator)의 일반적인 사항과 제약 사항 (1) | 2015.09.14 |