문제

쓰 내부는 루프를 요구하는 장소 structs 에 인접한 저장입니다.내가 알지 못하는 방법은 많은 이들의 structs 있을 것입니다.내 문제는 STL 의 vector 를 초기화 값을 0 으로,그래서 내가 무엇을 하든지,내가 비용을 발생시키는 초기화 플러스의 비용을 설정 struct의 멤버들의 값이 있습니다.

하는 방법은 없을 방지 초기화,또는 STL 같은 컨테이너가 크기 조정 가능한 연속된 스토리지 및 초기화되지 않은 요소가?

(나는 특정의 이 부분에 코드를 최적화해야,그리고 나는 특정 초기화는 상당한 비용이 소요됩니다.)

또한,내 의견은 아래에 대한 자세한 설명을 때 초기화가 발생합니다.

일부 코드:

void GetsCalledALot(int* data1, int* data2, int count) {
    int mvSize = memberVector.size()
    memberVector.resize(mvSize + count); // causes 0-initialization

    for (int i = 0; i < count; ++i) {
        memberVector[mvSize + i].d1 = data1[i];
        memberVector[mvSize + i].d2 = data2[i];
    }
}
도움이 되었습니까?

해결책

std::vector 해 초기화 값 배열에 어떻게든 의미하는 몇 가지 생성자(또는 사본-생성자)가 호출됩니다.의 동작 vector (또는 컨테이너 클래스)에 정의되지 않은 경우에 당신은에 액세스하는 초기화되지 않은 섹션의 배열면 초기화됩니다.

최선의 방법은 사용 reserve()push_back(), 도록 복사-생성자를 사용,피하 기본으로 건설입니다.

를 사용하여 당신의 예제 코드:

struct YourData {
    int d1;
    int d2;
    YourData(int v1, int v2) : d1(v1), d2(v2) {}
};

std::vector<YourData> memberVector;

void GetsCalledALot(int* data1, int* data2, int count) {
    int mvSize = memberVector.size();

    // Does not initialize the extra elements
    memberVector.reserve(mvSize + count);

    // Note: consider using std::generate_n or std::copy instead of this loop.
    for (int i = 0; i < count; ++i) {
        // Copy construct using a temporary.
        memberVector.push_back(YourData(data1[i], data2[i]));
    }
}

만의 문제가 전화 reserve() (나 resize())이 같은 결과가 발생할 수 있습 호출하여 복사-생성자보다 더 자주 필요가 있습니다.만약 당신이 할 수 있는 좋은 예측하기로 최종 크기의 배열을,그것은 더 나 reserve() 공간은 한 번 시작합니다.알지 못하는 경우 최종 크기는 하지만,적어도 매수를 최소화 될 수 있습니다.

현재 버전에서는 C++,내부 루프는 조금 비효율적으로 임시 값으로 구성되어 스택 사본을 건설하는 벡터를 메모리,그리고 마지막으로 임시 파괴되었습니다.그러나 다음 버전의 C++라는 기능이 있는 R 값을 참조(T&& 도)어떤 도움이 될 것입니다.

인터페이스 제공 std::vector 허용하지 않는 또 다른 옵션은 사용하는 몇 가지의 공장과 같은 클래스를 구성하는 값 이외의 다른 기본입니다.여기에는 거친 들이 본 것처럼 보이 구현되는 C++에서:

template <typename T>
class my_vector_replacement {

    // ...

    template <typename F>
    my_vector::push_back_using_factory(F factory) {
        // ... check size of array, and resize if needed.

        // Copy construct using placement new,
        new(arrayData+end) T(factory())
        end += sizeof(T);
    }

    char* arrayData;
    size_t end; // Of initialized data in arrayData
};

// One of many possible implementations
struct MyFactory {
    MyFactory(int* p1, int* p2) : d1(p1), d2(p2) {}
    YourData operator()() const {
        return YourData(*d1,*d2);
    }
    int* d1;
    int* d2;
};

void GetsCalledALot(int* data1, int* data2, int count) {
    // ... Still will need the same call to a reserve() type function.

    // Note: consider using std::generate_n or std::copy instead of this loop.
    for (int i = 0; i < count; ++i) {
        // Copy construct using a factory
        memberVector.push_back_using_factory(MyFactory(data1+i, data2+i));
    }
}

이 일을 하지 않는다는 의미가 있을 만드는 당신의 자신의 벡터 클래스입니다.이 경우 그것은 또한 복잡한 이야기는 간단한 예제입니다.하지만 시간이 있을 수 있습니다 어디를 사용하여 공장 기능은 다음과 같이 더 나은,예를 들면에 삽입하는 조건으로 다른 값,그리고 당신은 그렇지 않으면 무조건적으로 구축 비용이 많이 드는 임시지 않은 경우에도 실제로 필요합니다.

다른 팁

C++0x 추가 새로운 멤버 함수는 템플릿 emplace_back 하기 vector (에 의존하는 앞 템플릿과 완벽한 전달)를 제거한 모든 전적으로 임시 개체:

memberVector.emplace_back(data1[i], data2[i]);

에 명확하게 예약하()응답:필요하신 사용하실 수 있()함께 push_back().이 방법,기본 생성자를 호출하지 않고 각 요소에 대해지만,오히려 사본을 생성자입니다.당신은 여전히 발생하의 벌금을 설정하는 구조체에 스택,그리고 그런 다음 이를 복사하는 벡터입니다.다른 한편으로는 사용하는 경우

vect.push_back(MyStruct(fieldValue1, fieldValue2))

컴파일러 구성하는 것은 새 인스턴스에 직접 메모리 thatbelongs 을 벡터입니다.하는 방법에 따라 스마트 최적화 프로그램입니다.을 확인해야 합 생성된 코드를 찾을 수 있습니다.

에서는 C++11(부)사용할 수 있는 배열의 버전 unique_ptr 를 할당하는 초기화되지 않은 배열입니다.이것은 매우 stl 컨테이너,하지만 여전히 메모리를 관리하고 C-틱는 충분히 좋은 것입니다 여러 애플리케이션에 적합합니다.

auto my_uninit_array = std::unique_ptr<mystruct[]>(new mystruct[count]);

그래서 여기에 문제,크기를 조정하는 부름을 삽입하는 일을 복사본을 건설에서는 기본 구성 요소에 대한 각각의 새로 추가 요소입니다.이를 0 으로 당신이 비용을 작성해야 자신의 기본 생성자와 자신의 사본을 생성자를 비어 기능입니다.이렇게 당신의 사본을 생성자 아주 나쁜 생각이 할 것이기 때문에 휴식 std::벡터의 내부에 재 할당 알고리즘이 있습니다.

요약:당신이 할 수있을거야 이렇게 std::벡터입니다.

Err...

시도하는 방법:

std::vector<T>::reserve(x)

그것은 당신을 예약할 수 있는 충분한 메모리에 대한×항목 초기화하지 않고(벡터는 여전히 비어 있을 경우).따라서,없을 할당할 때까지 통해 갈 x.

두 번째 요점은 벡터지 않을 것이 값을 초기화를니다.당신은 당신을 테스트하는 코드를 디버깅?

후 검증에 대 g++,다음 코드:

#include <iostream>
#include <vector>

struct MyStruct
{
   int m_iValue00 ;
   int m_iValue01 ;
} ;

int main()
{
   MyStruct aaa, bbb, ccc ;

   std::vector<MyStruct> aMyStruct ;

   aMyStruct.push_back(aaa) ;
   aMyStruct.push_back(bbb) ;
   aMyStruct.push_back(ccc) ;

   aMyStruct.resize(6) ; // [EDIT] double the size

   for(std::vector<MyStruct>::size_type i = 0, iMax = aMyStruct.size(); i < iMax; ++i)
   {
      std::cout << "[" << i << "] : " << aMyStruct[i].m_iValue00 << ", " << aMyStruct[0].m_iValue01 << "\n" ;
   }

   return 0 ;
}

제공은 다음과 같은 결과를 생성합니다.

[0] : 134515780, -16121856
[1] : 134554052, -16121856
[2] : 134544501, -16121856
[3] : 0, -16121856
[4] : 0, -16121856
[5] : 0, -16121856

초기화는 당신을 본 아마이었는 유물이다.

[편집]한 후에 주석의 크기를 조정,수정 나의 코드를 추가하는 크기 조정 라인입니다.크기 조정을 효과적으로 통화의 기본 생성자체 내부에 벡터지만,기본 생성자를 사용하려면 아무것도하지 않는다면 아무것도가 초기화되...난 여전히 그것을 믿는 이슈(관리 첫 번째 시간을 전체 벡터 zerooed 다음과 같은 코드:

aMyStruct.push_back(MyStruct()) ;
aMyStruct.push_back(MyStruct()) ;
aMyStruct.push_back(MyStruct()) ;

그래서...:-/

[EDIT2]다음과 같이 이미 제공 Arkadiy,이 솔루션은 사용하는 인라인 생성자를 복용하여 원하는 매개 변수입니다.뭔가

struct MyStruct
{
   MyStruct(int p_d1, int p_d2) : d1(p_d1), d2(p_d2) {}
   int d1, d2 ;
} ;

이게 인라인에서 당신의 코드입니다.

하지만 당신은 어쨌든 연구의 코드와 프로파일 확인하이 조각의 코드에 병목 현상의 응용 프로그램입니다.

사용 std::vector::약()메소드가 있습니다.그것은 크기를 조정하지 않습니다 벡터,하지만 그것은 공간을 할당.

에서 당신의 댓글을 다른 포스터,그것은 다음과 같 당신은 왼쪽으로 malloc()과 친구들.벡터 못하게 당신이 생성되지 않은 요소입니다.

코드에서,그것은 다음과 같이 있을 벡터의 구조체로 구성되어 각각의 2 수.할 수 있는 대신 사용하여 2 벡터의 수?다음

copy(data1, data1 + count, back_inserter(v1));
copy(data2, data2 + count, back_inserter(v2));

지금 당신이 지불하지 않 복사하기 위한 구조체이됩니다.

당신이 정말로 주장하는 데 요소에 초기화되지 않은 희생 같은 방법을 앞(),(다),push_back(),부스트를 사용하는 벡터에서는 숫자입니다.그것은 당신이지도를 보존 기존 요소를 호출할 때 resize()...

당신이 사용할 수 있는 래퍼 유형 주위에 당신의 요소형,기본 생성자를 가지는 아무것도하지 않습니다.E.g.:

template <typename T>
struct no_init
{
    T value;

    no_init() { static_assert(std::is_standard_layout<no_init<T>>::value && sizeof(T) == sizeof(no_init<T>), "T does not have standard layout"); }

    no_init(T& v) { value = v; }
    T& operator=(T& v) { value = v; return value; }

    no_init(no_init<T>& n) { value = n.value; }
    no_init(no_init<T>&& n) { value = std::move(n.value); }
    T& operator=(no_init<T>& n) { value = n.value; return this; }
    T& operator=(no_init<T>&& n) { value = std::move(n.value); return this; }

    T* operator&() { return &value; } // So you can use &(vec[0]) etc.
};

를 사용:

std::vector<no_init<char>> vec;
vec.resize(2ul * 1024ul * 1024ul * 1024ul);

하 구조체는 스스로 해야에서 연속적인 메모리,또는 당신이 얻을 수 있습니 멀리로는 벡터의 구조체*?

벡터의 복사본을 만들고 당신이 무엇을 추가하고,그래서 사용하는 벡터의 포인터가 아닌 객체를 하나의 방법은 성능을 향상시킬 수 있습니다.

나는 생각하지 않는 STL 당신의 대답이다.당신이해야 자신의 종류의 솔루션을 사용하여 realloc().당신은 저장소의 포인터 및 크기,또는 수의 요소,그리고 사용하는 곳을 찾을 시작하는 요소를 추가하 후 realloc().

int *memberArray;
int arrayCount;
void GetsCalledALot(int* data1, int* data2, int count) {
    memberArray = realloc(memberArray, sizeof(int) * (arrayCount + count);
    for (int i = 0; i < count; ++i) {
        memberArray[arrayCount + i].d1 = data1[i];
        memberArray[arrayCount + i].d2 = data2[i];
    }
    arrayCount += count;
}

나는 뭔가를 다음과 같:

void GetsCalledALot(int* data1, int* data2, int count)
{
  const size_t mvSize = memberVector.size();
  memberVector.reserve(mvSize + count);

  for (int i = 0; i < count; ++i) {
    memberVector.push_back(MyType(data1[i], data2[i]));
  }
}

당신이 해야 한다는 것을 의미합니 ctor 유형에 저장된 memberVector,하지만 그는 작은 비용으로 줄 것이다 당신은 두 세계의 최고를;불필요한 초기화와 더 재할당을 하는 동안 발생합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top