'신규 게재 위치'에는 어떤 용도가 있습니까?


410

여기에 C ++의 "배치 새"를 사용한 사람이 있습니까? 그렇다면 무엇을 위해? 메모리 매핑 하드웨어에서만 유용 할 것 같습니다.


14
이것은 부스트 ​​할당 된 메모리 풀에서 객체 생성자를 호출하기 위해 내가 찾은 정보 일뿐입니다. (이러한 키워드를 사용하면 나중에 더 쉽게 찾을 수 있습니다).
사이드 쇼 밥

2
그것은에서 사용 은 C ++ 11 Wikipedia 기사 노동 조합의 생성자입니다.
HelloGoodbye

@HelloGoodbye, 재미있는! 연결 한 기사에서 왜 대신 p = pt할당 연산자를 사용하고 사용할 수 없습니까? 둘 사이의 차이점이 궁금합니다. 전자 는 Point를 호출하고 후자는 Call 생성자를 ? 그러나 나는 왜 하나가 다른 것보다 더 나은지 여전히 명확하지 않습니다. Pointnew(&p) Point(pt)operator=Point
Andrei-Niculae Petre

@ Andrei-NiculaePetre 새로운 배치를 직접 사용하지는 않았지만 현재 해당 클래스의 객체가없는 경우 복사 생성자와 함께 사용해야합니다. 그렇지 않으면 복사 할당 연산자를 사용해야합니다. 수업이 사소하지 않으면; 어떤 것을 사용하든 상관 없습니다. 같은 것은 물체의 파괴에도 적용됩니다. 사소하지 않은 클래스에 대해 올바르게 처리하지 않으면 이상한 동작이 발생할 수 있으며 경우에 따라 정의되지 않은 동작 이 발생할 수도 있습니다 .
HelloGoodbye

@ Andrei-NiculaePetre 사실, Wikipedia 기사 의 예제 는 이전 객체가 존재하지 않으며 하나를 생성해야한다고 가정하기 때문에 매우 나쁩니다. U::operator=방금 호출 된 경우에는 해당되지 않습니다 .
HelloGoodbye

답변:


364

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 : "게재 위치 삭제"가 있습니까? 를 참조하십시오 .


54
컨테이너 객체 (예 : 벡터)를 효율적으로 구현하기 위해이 기능이 필요하므로 더 이상 사용되지 않습니다. 자체 컨테이너를 작성하지 않는 경우에는이 기능을 사용할 필요가 없습니다.
Martin York

26
그렇지 않으면 자동으로 새로운 위치를 인식하지 않는 일부 플랫폼에서 끔찍한 두통으로 실행할 수도 사용법 #include <메모리>를 기억하는 것이 매우 중요하다
라몬 Zarazua B.

22
엄밀히 말하면, delete[]원래 char버퍼 를 호출 하는 것은 정의되지 않은 동작 입니다. 배치 newchar사용하면 저장소를 다시 사용하여 원본 객체 의 수명이 끝났습니다 . 이제 delete[] buf객체의 동적 유형을 더 이상 정적 유형과 일치하지 않도록 지정하면 동작이 정의되지 않습니다. 배치에 의해 사용되는 원시 메모리 를 사용 operator new/ operator delete할당 하는 것이 더 일관 적 new입니다.
CB Bailey

31
맥박 조정기에서 힙 사용을 확실히 건너 뛸 것입니다 :-)
Eli Bendersky

15
@RamonZarazua 잘못된 헤더 #include <new>입니다.
bit2shift

63

우리는 커스텀 메모리 풀과 함께 사용합니다. 스케치 만 :

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, ...);

이제 단일 메모리 영역에서 객체를 클러스터링하고, 매우 빠르지 만 할당을 해제하지 않는 할당자를 선택하고, 메모리 매핑을 사용하고, 풀을 선택하고이를 객체의 배치에 대한 인수로 전달하여 부과하려는 다른 의미 체계를 선택할 수 있습니다. 새로운 연산자.


1
네. 우리는 그것에 대해 상당히 영리하지만,이 질문에 대해서는 주제가 아닙니다.
Don Wakefield

2
@jdkoftinoff 실제 코드 샘플에 대한 링크가 있습니까? 나에게는 꽤 흥미로운 것 같습니다!
Victor

@DonWakefield이 풀에서 정렬을 어떻게 처리합니까? allocate()어딘가에 인수로 정렬을 전달해서는 안 됩니까?
Mikhail Vasilyev 2016 년

1
@MikhailVasilyev, 실제 구현에서는 물론 처리 할 것입니다. 예제 코드 만.
Don Wakefield

게재 위치가 잘못된 주소 인 경우 어떻게합니까 (0x0)?
Charlie

51

할당과 초기화를 분리하려는 경우에 유용합니다. STL은 새로운 배치를 사용하여 컨테이너 요소를 만듭니다.


35

실시간 프로그래밍에 사용했습니다. 일반적으로 시스템 시작 후 동적 할당 (또는 할당 해제)을 수행하고 싶지 않습니다. 시간이 얼마나 걸리는지 보장 할 수 없기 때문입니다.

내가 할 수있는 일은 큰 메모리 덩어리를 미리 할당하는 것입니다 (클래스에 필요한 모든 것을 담을 수있을만큼 큼). 그런 다음 런타임에 물건을 구성하는 방법을 알아 낸 후에는 새로운 위치를 사용하여 원하는 곳에 객체를 구성 할 수 있습니다. 내가 사용했던 한 가지 상황은 이기종 순환 버퍼를 만드는 데 도움이되었다는 것입니다 .

그것은 분명 희미한 마음을위한 것이 아니지만, 그에 대한 구문을 좀 나쁘게 만드는 이유입니다.


안녕하세요 TED, 솔루션에 대해 더 많은 정보를 공유해 주시겠습니까? 나는 미리 할당 된 솔루션을 생각하고 있지만 많은 진전을 얻지 못했습니다. 미리 감사드립니다!
Viet

1
실제로, 고유 한 원형 순환 버퍼 코드는 실제로 까다로운 부분이었습니다. 새로운 palcement는 약간 유쾌하게 보이지만 비교하면 전혀 문제가 없었습니다.
TED

26

alloca ()를 통해 스택에 할당 된 객체를 구성하는 데 사용했습니다.

뻔뻔한 플러그 : 나는 그것에 대해 블로그 여기 .


흥미로운 기사이지만 이것을 사용하는 이점을 이해하지 못했습니다 boost::array. 좀 더 확장 할 수 있습니까?
GrahamS

boost :: array를 사용하려면 배열의 크기가 컴파일 타임 상수 여야합니다. 이것은 그 제한이 없습니다.
Ferruccio

2
@ Ferruchio 이것은 꽤 멋지다. 나는 매크로가 약간 안전하지 않다는 것을 알았다. 예를 들어 x + 1이 전달되면 sizeof (type) * x + 1로 확장하여 올바르지 않습니다. 보다 안전하게하려면 매크로를 묶어야합니다.
Benj

alloca와 함께 사용하면 모든 객체에서 소멸자를 호출해야 할 때 예외가 발생하면 위험합니다.
CashCow

14

헤드 eek : 빙고! 당신은 그것을 완전히 얻었습니다-그것이 정확히 완벽한 것입니다. 많은 임베디드 환경에서 외부 제약 조건 및 / 또는 전체 사용 시나리오는 프로그래머가 객체 할당을 초기화와 분리하도록합니다. C ++은이를 "인스턴스화"라고 부릅니다. 그러나 생성자 작업이 동적 또는 자동 할당없이 명시 적으로 호출되어야 할 때마다 새로운 배치가 수행 방법입니다. 또한 하드웨어 구성 요소 (메모리 매핑 된 I / O)의 주소에 고정되어 있거나 어떤 이유로 든 고정 주소에 있어야하는 정적 개체에 대한 전역 C ++ 개체를 찾는 완벽한 방법입니다.


12

Variant 클래스 (예 : 여러 유형 중 하나 일 수있는 단일 값을 나타낼 수있는 객체)를 만드는 데 사용했습니다.

Variant 클래스가 지원하는 모든 값 유형이 POD 유형 (예 : int, float, double, bool) 인 경우 태그가있는 C 스타일 유니온이면 충분하지만 일부 값 유형을 C ++ 객체 ( 예를 들어 std :: string)의 경우 비 POD 데이터 유형은 공용체의 일부로 선언되지 않을 수 있으므로 C 공용체 기능은 수행하지 않습니다.

따라서 대신 Variant가 해당 유형의 값을 보유하도록 설정된 경우 충분히 큰 바이트 배열 (예 : sizeof (the_largest_data_type_I_support))을 할당하고 new를 사용하여 해당 영역에서 적절한 C ++ 객체를 초기화합니다. (물론 다른 비 POD 데이터 유형에서 전환 할 때 배치를 미리 삭제하십시오)


Erm, 비 POD 데이터 유형 Union ctor를 제공하는 한 UNION 내에서 선언 될 있습니다. ctor 는 아마도new non-POD 서브 클래스를 초기화 하기 위해 배치사용할 것입니다 . 참조 : stackoverflow.com/a/33289972/2757035 임의로 큰 바이트 배열을 사용 하여이 바퀴를 재창조하는 것은 인상적인 곡예이지만 완전히 불필요합니다. 그래서 내가 놓친 것은 무엇입니까? :)
underscore_d

6
C ++ 11 이전의 모든 C ++ 버전을 놓쳤습니다. 많은 경우 여전히 지원해야합니다. :)
Jeremy Friesner

10

새로운 배치는 직렬화 (예 : boost :: serialization)와 같이 매우 유용합니다. 10 년 동안의 C ++에서 이것은 새로운 배치가 필요한 두 번째 경우입니다 (면접을 포함하면 세 번째).


9

전역 또는 정적으로 할당 된 구조를 다시 초기화하려는 경우에도 유용합니다.

구식 C 방식은 memset()모든 요소를 ​​0으로 설정 하는 데 사용 되었습니다. v ++ 및 사용자 정의 객체 생성자로 인해 C ++에서는이를 수행 할 수 없습니다.

그래서 때때로 다음을 사용합니다

 static Mystruct m;

 for(...)  {
     // re-initialize the structure. Note the use of placement new
     // and the extra parenthesis after Mystruct to force initialization.
     new (&m) Mystruct();

     // do-some work that modifies m's content.
 }

1
그런 식으로 다시 초기화하기 전에 해당 파괴를 수행하지 않아도됩니까?
헤드 eek

[맞춤법으로 편집 됨] 일반적으로-수행합니다. 그러나 때때로 클래스가 메모리 나 다른 리소스를 할당하지 않는 것을 알고있을 때 (또는 메모리 풀을 사용할 때와 같이 외부 적으로 할당을 해제 한 경우)이 기술을 사용할 수 있습니다. v- 테이블 포인터를 덮어 쓰지 않도록 보장합니다. – nimrodm 16 시간 전
nimrodm

1
C에서도 모든 비트를 0으로 설정하는 것은 다른 유형이 아닌 정수 유형에 대해 0의 표현을 생성하도록 보장됩니다 (널 포인터는 0이 아닌 표현을 가질 수 있음).
curiousguy

@ curiousguy-기본 유형의 경우 정확합니다 (프로그램을 예측 가능하게 만들어 디버깅과 관련하여 유리합니다). 그러나 C ++ 데이터 유형에는 생성자가 제자리에서 실행되어 제대로 초기화됩니다.
nimrodm

9

실제로 삽입 된 요소 수에 필요한 최소한의 메모리보다 많은 메모리를 할당하는 모든 종류의 데이터 구조 (즉, 한 번에 하나의 노드를 할당하는 링크 된 구조 이외의 것)를 구현해야합니다.

테이크 컨테이너 좋아 unordered_map, vector또는 deque. 이들은 모두 단일 삽입마다 힙 할당이 필요하지 않도록 지금까지 삽입 한 요소에 필요한 최소 메모리보다 많은 메모리를 할당합니다. vector가장 간단한 예로 사용합시다 .

할 때 :

vector<Foo> vec;

// Allocate memory for a thousand Foos:
vec.reserve(1000);

... 실제로 수천 개의 Foos를 구성하지는 않습니다. 단순히 메모리를 할당 / 예약합니다. 경우 vector여기에 새로운 배치를 사용하지 않은, 그것은 기본적으로 건설 될 것이다 Foos사방을뿐만 아니라 심지어 당신도 처음에 삽입되지 않습니다 요소에 대한 소멸자를 호출 할 필요.

할당! = 건설, 해방! = 파괴

일반적으로 위와 같은 많은 데이터 구조를 구현하기 위해 말하면 메모리 할당 및 요소 생성을 하나의 불가분의 것으로 취급 할 수 없으며, 메모리 해제 및 요소 삭제를 하나의 불가분의 것으로 취급 할 수 없습니다.

생성자와 소멸자를 불필요하게 좌우로 호출하는 것을 피하기 위해 이러한 아이디어 사이에 분리가 있어야합니다. 그래서 표준 라이브러리는 std::allocator(메모리를 할당 / 해제 할 때 요소를 구성하거나 파괴하지 않습니다 *) 에서 아이디어를 분리합니다. 배치를 사용하여 요소를 수동으로 구성하고 소멸자를 명시 적으로 호출하여 요소를 수동으로 파괴하는 컨테이너를 사용하는 컨테이너.

  • 나는 디자인이 싫지만 std::allocator그것이 도망 치지 않을 다른 주제입니다. :-디

어쨌든, 기존 컨테이너로 만들 수 없었던 많은 범용 표준 호환 C ++ 컨테이너를 작성했기 때문에 많이 사용하는 경향이 있습니다. 그중에는 일반적인 경우 힙 할당을 피하기 위해 수십 년 전에 구축 한 작은 벡터 구현과 메모리 효율적인 트리 (한 번에 한 노드를 할당하지 않음)가 포함됩니다. 두 경우 모두 기존 컨테이너를 사용하여 실제로 구현할 수 없었기 때문에 placement new불필요한 왼쪽과 오른쪽에 생성자와 소멸자를 불필요하게 호출하는 것을 피해야했습니다.

당연히 사용자 지정 할당 자와 함께 사용하여 자유 목록과 같이 개별적으로 객체를 할당하는 경우 일반적으로 다음 placement new과 같이을 사용하고 싶을 것입니다 (예외 안전 또는 RAII를 방해하지 않는 기본 예).

Foo* foo = new(free_list.allocate()) Foo(...);
...
foo->~Foo();
free_list.free(foo);

8

커널을 빌드하는 경우 유용합니다. 디스크 나 페이지 테이블에서 읽은 커널 코드를 어디에 배치합니까? 어디로 가야하는지 알아야합니다.

또는 할당 된 공간이 많고 몇 개의 구조물을 서로 배치하려는 경우와 같은 매우 드문 상황입니다. 이들은 offsetof () 연산자 없이도 이런 식으로 압축 될 수 있습니다. 그러나 다른 트릭도 있습니다.

또한 일부 STL 구현은 std :: vector와 같은 새로운 배치를 사용한다고 생각합니다. 그런 식으로 2 ^ n 요소를위한 공간을 할당하며 항상 재 할당 할 필요는 없습니다.


메모리 할당을 줄이는 것이 메모리를 사용하는 주된 이유 중 하나이며 디스크에서 객체를로드하는 것과 같은 "트릭"
lefticus

C ++로 작성된 커널을 모른다. 대부분의 커널은 똑바로 C로 작성됩니다.
Adam Rosenfield

8
나는 OS 기초를 배운있는 운영 체제는 C ++로 작성 : sweb.sourceforge.net
mstrobl

8

나는 이것이 어떤 대답으로 강조되지 않았다고 생각하지만, 새로운 배치에 대한 또 다른 좋은 예와 사용법은 (메모리 풀을 사용하여) 메모리 조각화를 줄이는 것입니다. 이것은 내장 및 고 가용성 시스템에서 특히 유용합니다. 이 마지막 경우에는 24/365 일 동안 실행해야하는 시스템의 경우 조각화가없는 것이 매우 중요하므로 특히 중요합니다. 이 문제는 메모리 누수와 아무 관련이 없습니다.

매우 훌륭한 malloc 구현을 사용하더라도 (또는 유사한 메모리 관리 기능) 오랜 시간 조각화를 처리하는 것은 매우 어렵습니다. 어떤 시점에서 메모리 예약 / 릴리스 통화를 영리하게 관리하지 않으면 재사용하기 어려운 작은 간격 이 생길 수 있습니다 (새 예약에 할당). 따라서이 경우에 사용되는 솔루션 중 하나는 메모리 풀을 사용하여 사전에 애플리케이션 오브젝트에 대한 메모리를 할당하는 것입니다. 나중에 일부 객체에 대한 메모리가 필요할 때마다 새 배치 를 사용하여 이미 예약 된 메모리에 새 객체를 만듭니다.

이렇게하면 응용 프로그램이 시작되면 필요한 모든 메모리가 이미 예약되어 있습니다. 모든 새 메모리 예약 / 릴리스는 할당 된 풀로 이동합니다 (각각 다른 객체 클래스마다 하나씩 여러 개의 풀이있을 수 있음). 이 경우 간격이없고 시스템이 단편화를 겪지 않고 매우 오랜 기간 (년간) 실행될 수 있으므로 메모리 단편화가 발생하지 않습니다.

기본 메모리 할당 시스템이 조각화되기 때문에 VxWorks RTOS에서 실제로 이것을 실제로 보았습니다. 따라서 표준 new / malloc 방법을 통해 메모리를 할당하는 것은 기본적으로 프로젝트에서 금지되었습니다. 모든 메모리 예약은 전용 메모리 풀로 이동해야합니다.


8

그것은에 의해 사용되는 std::vector<>때문에 std::vector<>일반적으로이보다 더 많은 메모리 할당 objects에를 vector<>.


7

메모리 매핑 파일로 객체를 저장하는 데 사용했습니다.
구체적인 예는 많은 수의 큰 이미지를 메모리에 넣을 수있는 이미지 데이터베이스로 처리 한 것입니다.


7

"동적 유형"포인터 ( "후드 아래"섹션에서)에 대한 약간의 성능 핵 으로 사용되는 것을 보았습니다 .

그러나 여기에 작은 유형에 대한 빠른 성능을 얻는 데 사용하는 까다로운 트릭이 있습니다. 유지되는 값이 void * 안에 들어갈 수 있다면 실제로 새로운 객체를 할당하는 것을 귀찮게하지는 않습니다. .


보류중인 값이 void * 안에 들어갈 수 있다면 무엇을 의미합니까? 모든 포인터 유형을 void *에 할당 할 수 있습니다. 예를 들어 주시겠습니까?
anurag86

@ anurag86 : 64 비트 컴퓨터에서 void*8 바이트 가 걸립니다. 8 바이트 void*를 1 바이트로 가리키는 것은 조금 바보 bool입니다. 그러나 실제로 오버레이 전적으로 가능 bool상의를 void*많이처럼 union { bool b; void* v }. a라고 부르는 void*것이 실제로 bool(또는 a short또는 a float등) 인지 알 수있는 방법이 필요합니다 . 내가 링크 한 기사는 그 방법을 설명합니다. 그리고 원래 질문에 대답하기 위해 배치 newboola void*가 예상되는 곳에 (또는 다른 유형) 을 만드는 데 사용되는 기능입니다 (캐스트는 나중에 값을 얻거나 수정하는 데 사용됩니다).
Max Lybbert

@ anurag86 : 똑같지는 않지만 태그 포인터 ( en.wikipedia.org/wiki/Tagged_pointer )에 관심이있을 수 있습니다 .
Max Lybbert

6

네트워크에서받은 메시지를 포함하는 메모리를 기반으로 객체를 만드는 데 사용했습니다.


5

일반적으로 new new 배치는 '정상적인 new'의 할당 비용을 제거하는 데 사용됩니다.

내가 사용한 또 다른 시나리오는 문서 당 싱글 톤을 구현하기 위해 여전히 구성해야 할 객체 에 대한 포인터 에 액세스하고 싶었던 곳 입니다.



4

내가 실행 한 곳은 인접한 버퍼를 할당 한 다음 필요에 따라 객체로 채우는 컨테이너에 있습니다. 언급했듯이 std :: vector 가이 작업을 수행 할 수 있으며 MFC CArray 및 / 또는 CList의 일부 버전 이이 작업을 수행한다는 것을 알고 있습니다 (처음부터 실행했기 때문에). 버퍼 오버 할당 방법은 매우 유용한 최적화이며 새로운 시나리오 배치는 해당 시나리오에서 객체를 구성하는 유일한 방법입니다. 또한 직접 코드 외부에 할당 된 메모리 블록에 객체를 구성하는 데 사용되기도합니다.

자주 나오지는 않지만 비슷한 용량으로 사용했습니다. 그래도 C ++ 도구 상자에 유용한 도구입니다.


4

스크립트 엔진은 기본 인터페이스에서이를 사용하여 스크립트에서 기본 오브젝트를 할당 할 수 있습니다. 예는 Angelscript (www.angelcode.com/angelscript)를 참조하십시오.


3

xll 프로젝트의 fp.h 파일 ( http://xll.codeplex.com)을 참조하십시오 . 크기를 가지고 다니는 배열에 대한 "컴파일러의 보증되지 않는 처 미함 "문제를 해결합니다.

typedef struct _FP
{
    unsigned short int rows;
    unsigned short int columns;
    double array[1];        /* Actually, array[rows][columns] */
} FP;

2

C ++ in-place 생성자에 대한 킬러 사용은 다음과 같습니다. 캐시 라인에 정렬하고 다른 두 가지 기능이 있습니다. 다음은 5 사이클 이하의 단일 사이클 명령으로 2 경계의 모든 힘에 대한 초고속 포인터 정렬 알고리즘입니다 .

/* Quickly aligns the given pointer to a power of two boundary IN BYTES.
@return An aligned pointer of typename T.
@brief Algorithm is a 2's compliment trick that works by masking off
the desired number in 2's compliment and adding them to the
pointer.
@param pointer The pointer to align.
@param boundary_byte_count The boundary byte count that must be an even
power of 2.
@warning Function does not check if the boundary is a power of 2! */
template <typename T = char>
inline T* AlignUp(void* pointer, uintptr_t boundary_byte_count) {
  uintptr_t value = reinterpret_cast<uintptr_t>(pointer);
  value += (((~value) + 1) & (boundary_byte_count - 1));
  return reinterpret_cast<T*>(value);
}

struct Foo { Foo () {} };
char buffer[sizeof (Foo) + 64];
Foo* foo = new (AlignUp<Foo> (buffer, 64)) Foo ();

이제는 얼굴에 미소를 짓지 않습니다 (:-). 나는 ♥♥♥ C ++ 1x

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.