program tip

pimpl에 unique_ptr을 어떻게 사용합니까?

radiobox 2020. 12. 5. 09:34
반응형

pimpl에 unique_ptr을 어떻게 사용합니까?


다음은 pimpl에 unique_ptr을 사용하려고 할 때 표시되는 내용을 단순화 한 것입니다. 나는 정말로 클래스가 포인터를 소유하기를 원하기 때문에 unique_ptr을 선택했습니다. pimpl 포인터와 클래스의 수명이 동일하기를 원합니다.

어쨌든 다음은 헤더입니다.

#ifndef HELP
#define HELP 1

#include <memory>

class Help
{

public:

  Help(int ii);
  ~Help() = default;

private:

  class Impl;
  std::unique_ptr<Impl> _M_impl;
};

#endif // HELP

출처는 다음과 같습니다.

#include "Help.h"

class Help::Impl
{
public:
  Impl(int ii)
  : _M_i{ii}
  { }

private:

  int _M_i;
};

Help::Help(int ii)
: _M_impl{new Help::Impl{ii}}
{ }

나는 이것들을 라이브러리로 잘 컴파일 할 수 있습니다. 하지만 테스트 프로그램에서 사용하려고하면

ed@bad-horse:~/ext_distribution$ ../bin/bin/g++ -std=c++0x -o test_help test_help.cpp Help.cpp
In file included from /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
                 from Help.h:4,
                 from test_help.cpp:3:
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Help::Impl]':
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:245:4:   required from 'void std::unique_ptr<_Tp, _Dp>::reset(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>; std::unique_ptr<_Tp, _Dp>::pointer = Help::Impl*]'
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:169:32:   required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>]'
Help.h:6:7:   required from here
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:63:14: error: invalid application of 'sizeof' to incomplete type 'Help::Impl'

이것은 잘 알려진 안전 기능 입니다. 나는 따르려고 노력했다.

내 문제는 헤더에 Help :: Impl 선언을 넣으면 pimpl의 장점을 제거하는 것처럼 보입니다. 클래스 레이아웃은 사용자에게 표시됩니다. 정의는 숨겨져 있지만 Help 클래스와 private 멤버로 그렇게 할 수 있습니다. 또한 Impl 선언을 포함하면 별도로 유지하고 싶었던 새로운 헤더가 제공됩니다.

What am I missing? What do folks put in an Impl declaration and where? Am I doing the Help dtor wrong? Argh!


I believe that your test_help.cpp actually sees the ~Help() destructor that you declared default. In that destructor, the compiler tries to generate the unique_ptr destructor, too, but it needs the Impl declaration for that.

So if you move the destructor definition to the Help.cpp, this problem should be gone.

-- EDIT -- You can define the destructor to be default in the cpp file, too:

Help::~Help() = default;

Note this from unique_ptr definition:

std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the pImpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr.

참고URL : https://stackoverflow.com/questions/9020372/how-do-i-use-unique-ptr-for-pimpl

반응형