2010-07-28 3 views
4

나는 :: 내가 최대 크기를 알 수있는 값의 벡터를 성병을 가지고 있지만 실제 크기는 사용 중에 달라집니다 : setupBuffer에, 나는의 시작에 대한 포인터를 얻기 위해 필요vector :: reserve()에 의해 할당 된 버퍼의 주소는 어떻게 얻을 수 있습니까?

void setupBuffer(const size_t maxSize) { 
    myVector.reserve(maxSize); 
} 

void addToBuffer(const Value& v) { 
    myVector.push_back(v); 

    if (myVector.size() == maxSize) { 
    // process data... 
    myVector.clear(); 
    } 
} 

그러나 myVector의 데이터. 제 3 자 라이브러리를 사용하고 있는데이 포인터를 "프로세스 데이터 ..."섹션에서 사용한 호출에 사용할 수 있도록 캐시해야합니다.

void setupBuffer(const size_t maxSize) { 
    myVector.reserve(maxSize); 

    cachePtr(&(myVector[0])); // doesn't work, obviously 
} 

나는 벡터에 추가 된 요소의 수를 의미하는 vector.size()를 사용하여 원하는대로, 정면) (벡터의 크기를 조정하고 싶지 않아요.

그래서 할당 후 벡터 버퍼에 대한 포인터를 얻을 수있는 방법이 있습니까 (reserve())? 요소가 있기 전에? 나는 버퍼가 존재한다고 상상할 것이다. (push_back의 값의 수를 제한하는 한 움직이지 않을 것이다.) 아마도 이것은 보장되지 않을까?

+2

왜 포인터를 필요할 때 안전하게 읽는 대신 캐시해야합니까? –

+0

특정 파일 형식에 대한 입출력을 위해 타사 라이브러리를 사용하고 있습니다. 그것이 작동하는 방식은 포인터와 최대 크기를 보내어 라이브러리에 '버퍼'를 설정하는 것입니다. 그런 다음 비동기 적으로 호출 할 수 있습니다. 디스크에 데이터를 플러시하는 'write'. maxSize를 쳤을 때마다 포인터를 설정할 수는 있지만 추가 오버 헤드가 될 수 있습니다 (테스트해야하는 정도). 그래도 좋은 지적이다. – Ryan

+0

이 질문은 포인터를 얻는 방법을 묻지 만 대답을 얻으면 그 포인터로 할 수있는 것에 대한 대답이 다릅니다. 그 문제를 직접 다루는 질문은 [std :: vector :: reserve safe 뒤에 원시 포인터에 액세스합니까?] (http://stackoverflow.com/questions/8228072/is-accessing-the-raw-pointer)를 참조하십시오. -after-stdvectorreserve-safe) –

답변

4

예약 된 용량을 초과하지 않는 한 벡터 버퍼는 예약 된 후에 이동되지 않습니다. 문제는 첫 번째 요소에 대한 포인터를 얻는 것입니다. 분명한 대답은 하나의 가짜 항목을 벡터에 넣고 포인터를 가져 와서 제거하는 것입니다.

라이브러리가 포인터가 아니라 함수를 수용하면 버퍼에 액세스해야 할 때 호출하는 것이 더 좋을 것입니다. 버퍼에 실제 내용이있을 때까지 주소를 가져 오지 못하게 할 수 있습니다. 그러나, 나는 당신이 도서관을 다시 쓸 사치가 없다는 것을 알고 있습니다.

+0

그래, 내가하는 일이야. 감사. – Ryan

+0

나에게서 좋은 아이디어,'+ 1'. 기술적으로 이것은 아직 정의되지 않은 동작이지만 실제로는 모든 구현에서 실제로 작동 할 것입니다. – sbi

+1

@sbi 이것이 왜 UB가 될지 모르겠다. –

2

No. 아니요 지수가 size 이상인 의사의 모든 요소에 액세스 할 수 없습니다. 크기 조정은 여기에서 유일한 옵션입니다.

은 무엇 당신이 할 수있는 것은 같은 :

myvec.resize(SOME_LARGE_VALUE); 
myLibrary(&myVec[0]); 
myvec.resize(GetSizeUsedByLibrary()); 

크기를 조정

는, 벡터의 요소가 새 크기 위의 인덱스를 가지고있는 것을 제외하고, 파괴되지 않는다. 크기 조정에 설정된 숫자 아래의 요소는 그대로 두었습니다. Example using std::basic_string, but equally applicable to vector

+0

예, 현재 진행중입니다. myVector.reserve (maxSize); myVector.resize (1); cachePtr (& myVector [0]); myVector.clear(); 작동하는 것으로 보입니다. 그냥 깨끗한 방법이 있기를 바랐습니다. 감사. – Ryan

+0

@ Ryan : 그건 잘못되었습니다. 아마도 C API'cachePtr'는 벡터의 첫 번째 요소를 지나치게 액세스합니다. 이는 정의되지 않은 동작이 있음을 의미합니다. 유효한 동작을 위해서는'capacity()'가 아니라'size()'아래에 있어야합니다. 작동하는 것처럼 보일 수 있습니다. 정의되지 않은 동작에 대한 유효한 대답은 "작동하는 것"입니다. –

-1

주변에는 많은 해킹이 있습니다.

typedef std::vector<MyItem, MyAllocator> myvector_t; 
가 MyAllocator에서 버퍼 할당을 고정 제공 한 후

하고 (벡터의 생성자의 arguemnt

+0

- 정의되지 않은 동작은 -1입니다. 벡터는 크기를 조정할 때 기본 구성 요소로 이동하게되므로 할당자가있는 경우에도 벡터의 이전 크기보다 큰 내용이 삭제됩니다. –

+0

흥미로운 제안이지만 할당은 실제로 문제가 아닙니다. 포인터를 std :: vector 밖으로 가져 오는 방법에 대한 API 문제가 더 많습니다. 사용자 정의 할당자가 도움이되는지 확신 할 수 없습니다. – Ryan

+0

@Billy ONeal - 아니요, 크기가 잘 알려진 경우 할당 자의 생성자에서 버퍼를 한 번 할당해야합니다. 그런 다음 재 할당을 방지해야합니다 (예 : 어설 션). 모든 할당은 할당 자의 초기 버퍼 내에서 수행되어야합니다. – Dewfy

0

당신이 시도해 봤어 전면으로이 할당 인스턴스를 전달합니다, 두 번째 템플릿 인수 우선 할당 -하지만 난 당신에게 유효한 방법을 추천합니다)? 또한 요소를 push_back하고 주소를 가져온 다음 지울 수 있습니다.

이 모든 내용은 보장 할 수는 없지만 벡터 <의 출처를 읽어보아야 만 괜찮은지 확인할 수 있습니다. 또한 데이터에 대한 포인터를 가지고 있으며 결코 움직이지 않는 자신 만의 벡터를 꽤 쉽게 굴릴 수 있습니다.

+2

vector에서 front()이 [0]과 어떻게 다른지는 잘 모릅니다. 참조를 반환하기 때문에 최소한 하나의 생성 된 객체가 있어야합니다. – Ryan

+0

나는 예비가 그것을 창조했다는 것을 생각하고 [0] 존재하지 않는 성분에 접근에 관하여 넋두리하고 있었다는 것을 생각한다. 프론트()가 경계를 검사했는지 궁금 해서요 (내가 본 문서는 말하지 않았습니다). 요소를 추가하고 지울 수 있습니다. –

관련 문제