여기에 C ++의 “배치 새”를 사용한 사람이 있습니까? 그렇다면 무엇을 위해? 메모리 매핑 하드웨어에서만 유용 할 것 같습니다.
답변
Placement new를 사용하면 이미 할당 된 메모리에 객체를 구성 할 수 있습니다.
객체의 여러 인스턴스를 생성해야 할 때 최적화를 위해이 작업을 수행 할 수 있으며 새 인스턴스가 필요할 때마다 메모리를 다시 할당하지 않는 것이 더 빠릅니다. 대신 한 번에 모든 개체를 사용하고 싶지 않더라도 여러 개체를 보유 할 수있는 메모리 청크에 대해 단일 할당을 수행하는 것이 더 효율적일 수 있습니다.
DevX는 좋은 예입니다 .
표준 C ++는 또한 사전 할당 된 버퍼에 객체를 생성하는 새로운 연산자 배치를 지원합니다. 메모리 풀, 가비지 콜렉터를 빌드하거나 성능 및 예외 안전이 가장 중요한 경우에 유용합니다 (메모리가 이미 할당되어 있으므로 할당 실패의 위험이 없으며 사전 할당 된 버퍼에 오브젝트를 구성하는 데 시간이 덜 걸립니다) :
char *buf = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi"); // placement new
string *q = new string("hi"); // ordinary heap allocation
또한 중요한 코드의 특정 부분 (예 : 심박 조율기에서 실행 한 코드)에서 할당 실패가 발생하지 않도록 할 수도 있습니다. 이 경우 메모리를 더 일찍 할당하려면 중요 섹션 내에서 새로 배치를 사용하십시오.
배치 배치 해제 새로운 기능
메모리 버퍼를 사용하는 모든 객체의 할당을 해제해서는 안됩니다. 대신 원래 버퍼 만 삭제해야합니다. 그런 다음 클래스의 소멸자를 수동으로 호출해야합니다. 이에 대한 제안은 Stroustrup의 FAQ : “게재 위치 삭제”가 있습니까? 를 참조하십시오 .
답변
우리는 커스텀 메모리 풀과 함께 사용합니다. 스케치 만 :
class Pool {
public:
Pool() { /* implementation details irrelevant */ };
virtual ~Pool() { /* ditto */ };
virtual void *allocate(size_t);
virtual void deallocate(void *);
static Pool::misc_pool() { return misc_pool_p; /* global MiscPool for general use */ }
};
class ClusterPool : public Pool { /* ... */ };
class FastPool : public Pool { /* ... */ };
class MapPool : public Pool { /* ... */ };
class MiscPool : public Pool { /* ... */ };
// elsewhere...
void *pnew_new(size_t size)
{
return Pool::misc_pool()->allocate(size);
}
void *pnew_new(size_t size, Pool *pool_p)
{
if (!pool_p) {
return Pool::misc_pool()->allocate(size);
}
else {
return pool_p->allocate(size);
}
}
void pnew_delete(void *p)
{
Pool *hp = Pool::find_pool(p);
// note: if p == 0, then Pool::find_pool(p) will return 0.
if (hp) {
hp->deallocate(p);
}
}
// elsewhere...
class Obj {
public:
// misc ctors, dtors, etc.
// just a sampling of new/del operators
void *operator new(size_t s) { return pnew_new(s); }
void *operator new(size_t s, Pool *hp) { return pnew_new(s, hp); }
void operator delete(void *dp) { pnew_delete(dp); }
void operator delete(void *dp, Pool*) { pnew_delete(dp); }
void *operator new[](size_t s) { return pnew_new(s); }
void *operator new[](size_t s, Pool* hp) { return pnew_new(s, hp); }
void operator delete[](void *dp) { pnew_delete(dp); }
void operator delete[](void *dp, Pool*) { pnew_delete(dp); }
};
// elsewhere...
ClusterPool *cp = new ClusterPool(arg1, arg2, ...);
Obj *new_obj = new (cp) Obj(arg_a, arg_b, ...);
이제 단일 메모리 영역에서 객체를 클러스터링하고, 매우 빠르지 만 할당을 해제하지 않는 할당자를 선택하고, 메모리 매핑을 사용하고, 풀을 선택하고이를 객체의 배치에 대한 인수로 전달하여 부과하려는 다른 의미 체계를 선택할 수 있습니다. 새로운 연산자.
답변
할당과 초기화를 분리하려는 경우에 유용합니다. STL은 새로운 배치를 사용하여 컨테이너 요소를 만듭니다.
답변
실시간 프로그래밍에 사용했습니다. 일반적으로 시스템 시작 후 동적 할당 (또는 할당 해제)을 수행하고 싶지 않습니다. 시간이 얼마나 걸리는지 보장 할 수 없기 때문입니다.
내가 할 수있는 일은 큰 메모리 덩어리를 미리 할당하는 것입니다 (클래스에 필요한 모든 것을 담을 수있을만큼 큼). 그런 다음 런타임에 물건을 구성하는 방법을 알아 낸 후에는 새로운 위치를 사용하여 원하는 곳에 객체를 구성 할 수 있습니다. 내가 사용했던 한 가지 상황은 이기종 순환 버퍼를 만드는 데 도움이되었다는 것입니다 .
그것은 분명 희미한 마음을위한 것이 아니지만, 그에 대한 구문을 좀 나쁘게 만드는 이유입니다.
답변
alloca ()를 통해 스택에 할당 된 객체를 구성하는 데 사용했습니다.
뻔뻔한 플러그 : 나는 그것에 대해 블로그 여기 .
답변
헤드 eek : 빙고! 당신은 그것을 완전히 얻었습니다-그것이 정확히 완벽한 것입니다. 많은 임베디드 환경에서 외부 제약 조건 및 / 또는 전체 사용 시나리오는 프로그래머가 객체 할당을 초기화와 분리하도록합니다. C ++은이를 “인스턴스화”라고 부릅니다. 그러나 생성자 작업이 동적 또는 자동 할당없이 명시 적으로 호출되어야 할 때마다 새로운 배치가 수행 방법입니다. 또한 하드웨어 구성 요소 (메모리 매핑 된 I / O)의 주소에 고정되어 있거나 어떤 이유로 든 고정 주소에 있어야하는 정적 개체에 대한 전역 C ++ 개체를 찾는 완벽한 방법입니다.
답변
Variant 클래스 (예 : 여러 유형 중 하나 일 수있는 단일 값을 나타낼 수있는 객체)를 만드는 데 사용했습니다.
Variant 클래스가 지원하는 모든 값 유형이 POD 유형 (예 : int, float, double, bool) 인 경우 태그가있는 C 스타일 유니온이면 충분하지만 일부 값 유형을 C ++ 객체 ( 예를 들어 std :: string)의 경우 비 POD 데이터 유형은 공용체의 일부로 선언되지 않을 수 있으므로 C 공용체 기능은 수행하지 않습니다.
따라서 대신 Variant가 해당 유형의 값을 보유하도록 설정된 경우 충분히 큰 바이트 배열 (예 : sizeof (the_largest_data_type_I_support))을 할당하고 new를 사용하여 해당 영역에서 적절한 C ++ 객체를 초기화합니다. (물론 다른 비 POD 데이터 유형에서 전환 할 때 배치를 미리 삭제하십시오)