[effective STL] 항목 16 : 기존 C API에 vector와 string 넘기기

2015. 12. 26. 23:03프로그래밍/Effective STL

728x90
728x90

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 컨테이너에 복사하는 아이디어는 항상 모든 경우에 동일하게 적용할 수 있다.

728x90
반응형