2014-12-24 1 views
2

나는 C++을 배우고 있으며 새로운 문제에 대해 다시 한 번 비틀 거렸다.C++ 새로운 C 배열 할당, RAII 또는 간단한 shared_ptr/boost :: shared_array

라이브러리를 사용할 수 있도록 C 배열을 할당해야하지만, 안전한 방법으로 사용해야합니다. 나는 이미 그 삭제 [] 발견; 방법의 끝에서 비참하게 실패합니다. 좋은하지

OLD :

float *buf; 

try { 
    buf = new float[daswidth*chans_info.chans*sizeof(float)]; 
} 
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution. 
{ 
    if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what()); 
    return; // skip this iteration then. 
} 

//... OUR CODE 

delete[] buf; 

내가 예전 할당 및 삭제하는 대신 완벽하게 작동하는 사용하는 tryed 그래서 :

float *buf; 

std::shared_ptr<float> safe_buf(new float[daswidth*chans_info.chans*sizeof(float)], [](float *p) { delete[] p; }); 

// OR BOOST EQUIVALENT 
boost::shared_array<float> safe_buf(new float[daswidth*chans_info.chans*sizeof(float)]); 

buf = safe_buf.get(); 

우리가 누설하지 않는, 모두가 행복하다 . 그러나 new_alloc을 잡는 법은 지금 던졌습니다.

새 {} 범위에서 shared_ptr을 할당 할 예정이라면 ... 파괴 된 이후에 나에게 ... 나 같은 미래에 대해 나에게 설명해주십시오. 이 경우 예외 처리 방법은 무엇입니까?

+4

'std :: vector'를 사용할 수없는 이유가 있습니까? –

+0

'std :: vector'는 실제로 그것을 초기화 할 때 생성되는'T *'를 포함합니다. 수표와 함수를 사용할 때 호출되는 오버 헤드는 약간 있지만 오버 헤드는 확실히 있습니다. –

+0

'sizeof (float)'는 여기에서 의심스러워 보입니다. 당신의 유스 케이스가 무엇인지 모르겠지만,'new float [n * sizeof (float)]'는'n * sizeof (float)'가 아닌'n * sizeof (float)'float를 할당합니다. 너도 알다시피. – milleniumbug

답변

3

std::unique_ptr-shared_ptr이 바람직합니다. 그것은 훨씬 빠릅니다. Ben 말했듯이

std::unique_ptr<float[]> buf; //construct 

try { 
    buf.reset(new float[daswidth*chans_info.chans*sizeof(float)]); //give memory 
} 
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution. 
{ 
    if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what()); 
    return; // skip this iteration then. 
} 

그러나,이 같은 float[]을 사용할 이유는 거의 없다. 대신 std::vector을 사용하십시오. 물론 대부분의 C interop에 대해서도 그렇습니다. C 코드 이제까지 당신을 위해 포인터를 "재 할당"한다면

std::vector<float> buf; 

try { 
    buf.resize(daswidth*chans_info.chans*sizeof(float)); //give memory 
} 
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution. 
{ 
    if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what()); 
    return; // skip this iteration then. 
} 

function_expecting_float_pointer(buf.data()); //use .data() to get the `float*` 

* std::vector를 사용하지 마십시오. 대신에 std::unique_ptr을 사용하고 (1) 메모리를 해제하고, (2) C로 패스하고, (3) C에서 반환 된 포인터로 리셋하십시오.

+0

덕분에 .reset이 내가 필요한 것입니다. 새로운 데이터를 할당 할 때 ptr의 크기를 재설정하는 것은 내가 알지 못했던 방법입니다. 하지만, 한가지 질문 - c 배열과 동일한 사용법 내에서 벡터보다 더 빠른 c 배열이 아닙니까? – Tomas

+1

@Arnas : C 배열은 기본적으로 데이터를 초기화하지 않으며, 'vector'는 기본적으로 요소를 초기화하려고 시도합니다. '벡터'를 정확하고 신중하게 사용하면 속도가 동일 해 지지만, 자신이하는 일을 모를 경우 이론적으로는 약간 느려질 수 있습니다. 그러나 항상 훨씬 쉽고 안전합니다. 그걸 써. 항상. –

+0

글쎄, 내 경우에는 unique_ptr을 선호 할 것이다. 왜냐하면 전혀 필요하지 않은 100Hz 속도로 전체 배열을 초기화 할 것이기 때문이다. – Tomas