shared_ptr
사용자 지정 할당 자 와 사용자 지정 삭제 기가 있다고 가정 해보십시오.
표준에서 삭제 프로그램을 저장할 위치에 대한 내용을 찾을 수 없습니다. 사용자 지정 할당자가 삭제 프로그램의 메모리에 사용될 것이라고 말하지 않으며 그렇지 않을 것이라고 말하지 않습니다 .
이것이 지정되지 않았습니까? 아니면 뭔가 빠졌습니까?
답변
C ++ 11의 util.smartptr.shared.const / 9 :
효과 : 객체 p와 삭제 기 d를 소유 한 shared_ptr 객체를 구성합니다. 두 번째와 네 번째 생성자는 내부 용으로 메모리를 할당하기 위해 a의 사본을 사용해야합니다.
두 번째와 네 번째 생성자에는 다음과 같은 프로토 타입이 있습니다.
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
최신 초안에서 util.smartptr.shared.const / 10은 다음과 같은 목적으로 사용됩니다.
효과 : 객체 p와 삭제 기 d를 소유 한 shared_ptr 객체를 구성합니다. T가 배열 유형이 아닌 경우 첫 번째 및 두 번째 생성자는 p와 shared_from_this를 활성화합니다. 두 번째와 네 번째 생성자는 내부 용으로 메모리를 할당하기 위해 a의 사본을 사용해야합니다. 예외가 발생하면 d (p)가 호출됩니다.
따라서 할당 된 메모리에 할당해야 할 경우 할당자가 사용됩니다. 현재 표준 및 관련 결함 보고서를 기반으로, 할당은 필수가 아니라위원회가 가정합니다.
-
의 인터페이스가 있지만
shared_ptr
결코 제어 블록 및 모든 없습니다 구현 할 수shared_ptr
와weak_ptr
링크 된 목록에 넣어가, 실제로 이러한 구현은 없다. 또한, 예를 들어, 문구use_count
가 공유 되는 것으로 가정하여 문구가 수정되었습니다 . -
삭제자는 구성 가능한 이동 만 필요합니다. 따라서에 여러 사본을 보유 할 수 없습니다
shared_ptr
.
삭제 기를 특수하게 설계 shared_ptr
하여 shared_ptr
삭제 하고 스페셜 이 삭제 될 때 이동 하는 구현을 상상할 수 있습니다 . 구현이 준수하는 것처럼 보이지만 특히 사용 횟수에 제어 블록이 필요할 수 있기 때문에 이상합니다.
내가 찾은 관련 예탁 증서 : 545 , 575 , 2434 , (모든 구현이 제어 블록을 사용하는 것을 인정 다소을 의무화하는 멀티 스레딩 제약을 의미하는 것) 2802 Deleter가 만 작도 이동해야하는 (따라서 구현 어디 방지 삭제는 여러 개의 사이에 복사됩니다 shared_ptr
).
답변
에서 표준 : : shared_ptr의 우리가 있습니다 :
제어 블록은 다음을 보유한 동적으로 할당 된 객체입니다.
- 관리 객체 또는 관리 객체 자체에 대한 포인터;
- 삭제 기 (유형 소거);
- 할당 자 (유형 소거);
- 관리 객체를 소유 한 shared_ptr의 수;
- 관리 객체를 나타내는 weak_ptr의 수
그리고 std :: allocate_shared에서 다음 을 얻습니다.
template< class T, class Alloc, class... Args >
shared_ptr<T> allocate_shared( const Alloc& alloc, Args&&... args );
공유 포인터 의 제어 블록 과 T 개체 모두에 대해 하나의 할당 을 사용하기 위해 T 형식의 개체를 구성하고 std :: shared_ptr […]에 래핑 합니다.
그래서처럼 보이는 표준 : allocate_shared 를 할당해야 deleter
당신과 함께 Alloc
.
편집 : 그리고 n4810
§20.11.3.6 생성 [util.smartptr.shared.create]
모두에 적용되는 1 개 공통 요구 사항은
make_shared
,allocate_shared
,make_shared_default_init
,와allocate_shared_default_init
달리 명시되지 않는 한 과부하, 아래에 설명되어 있습니다.[…]
7 비고 : (7.1) — 구현은 하나 이상의 메모리 할당을 수행하지 않아야합니다. [참고 : 이것은 침입 스마트 포인터와 동등한 효율성을 제공합니다. — 끝 참고]
[모든 것의 헛소리]
표준 그래서 말하는 std::allocate_shared
해야 사용 Alloc
제어 블록.
답변
나는 이것이 불특정이라고 믿는다.
관련 생성자의 사양은 다음과 같습니다. [util.smartptr.shared.const] / 10
template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
효과 : 구축
shared_ptr
객체 소유 객체p
와 Deleter가를d
. 되면T
배열 유형이 아닌, 제 1 및 제 2 활성화 생성자shared_from_this
로p
. 두 번째와 네 번째 생성자 는a
내부 용으로 메모리를 할당 하기 위해 사본을 사용해야 합니다. 예외가 발생하면d(p)
이 호출됩니다.
이제 내 구현에는 내부 사용을 위해 메모리가 필요할 때을 사용하여 수행된다는 해석이 a
있습니다. 구현에서이 메모리를 사용하여 모든 것을 배치해야한다는 의미는 아닙니다. 예를 들어, 이상한 구현이 있다고 가정하십시오.
template <typename T>
class shared_ptr : /* ... */ {
// ...
std::aligned_storage<16> _Small_deleter;
// ...
public:
// ...
template <class _D, class _A>
shared_ptr(nullptr_t, _D __d, _A __a) // for example
: _Allocator_base{__a}
{
if constexpr (sizeof(_D) <= 16)
_Construct_at(&_Small_deleter, std::move(__d));
else
// use 'a' to allocate storage for the deleter
}
// ...
};
이 구현이 “사본을 a
위해 메모리를 할당 하기 위해 사본을 사용합니까?” 그렇습니다. 를 사용하지 않고는 메모리를 할당하지 않습니다 a
. 이 순진한 구현에는 많은 문제가 있지만 shared_ptr
포인터에서 직접 생성되고 결코 복사되거나 이동되거나 참조되지 않으며 다른 합병증이없는 가장 단순한 경우를 제외하고 할당자를 사용하도록 전환한다고 가정 해 봅시다 . 요점은, 우리가 유효한 구현이 그 자체로는 이론적으로 존재할 수 없다는 것을 증명하지 못한다고 상상하지 못하기 때문입니다. 나는 실제로 그러한 구현이 실제 세계에서 발견 될 수 있다고 말하지는 않으며 표준이 적극적으로 그것을 금지하지 않는 것 같습니다.