Skip to content

Latest commit

ย 

History

History
168 lines (136 loc) ยท 5.43 KB

File metadata and controls

168 lines (136 loc) ยท 5.43 KB

22. Pimpl ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ• ๋•Œ๋Š” ํŠน์ˆ˜ ๋ฉค๋ฒ„ํ•จ์ˆ˜๋“ค์„ ๊ตฌํ˜„ํŒŒ์ผ์—์„œ ์ •์˜ ํ•˜๋ผ

๋ญ”์†Œ๋ฆฌ์ž„?

ํด๋ž˜์Šค์˜ ์ž๋ฃŒ๋ฉค๋ฒ„๋“ค์„ ๊ตฌํ˜„ํด๋ž˜์Šค(or ๊ตฌ์กฐ์ฒด)๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋กœ ๋Œ€์ฒดํ•˜์ž. (์ด๋Ÿฐ์ง“์„ pimpl ๊ด€์šฉ๊ตฌ๋ผ๊ณ  ํ•œ๋‹ค.)

์™œ?

ํด๋ž˜์Šค ํ•ด๋”๊ฐ„์˜ ์˜์กด์„ฑ์ด ํด์ˆ˜๋ก ์ปดํŒŒ์ผ์ด ๋Šฆ์–ด์ง€๊ณ  ์ปดํŒŒ์ผ ๋ฒ”์œ„๋„ ์ปค์ง„๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ์˜์กด์„ฑ์„ ์ค„์—ฌ๋ณด์ž. (๊ทธ์™ธ ํ•ด๋”์— ์˜คํƒ€๋‚˜๋ฉด ๋นŒ๋“œ ์—๋Ÿฌ ๋Œ€๋ฐ•)

//widget.h
#include "gadget.h"ย 
#include <string>
#include <vector>

class Widget_98
{
public:
  Widget_98() {};
  ~Widget_98() {};
private:
  std::string name;
  std::vector<double> data;
  Gadget g1, g2, g3;ย ย //Gadget ์‚ฌ์šฉ์ž ์ •์˜ Class
 };
 
 /**
 1. widget์€ ๋ฐ˜๋“œ์‹œ ๋ฉค๋ฒ„๋ณ€์ˆ˜ ํƒ€์ž…์„ ์•Œ์ˆ˜ ์žˆ๋Š” ํ•ด๋”๋ฅผ include ํ•ด์•ผํ•œ๋‹ค.
 2. gadget.h๊ฐ€ ๋ฐ”๋€Œ๋ฉด widget.h๋ฅผ includeํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  ํŒŒ์ผ์ด ์ปดํŒŒ์ผ์‹œ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค->์˜์กด์„ฑ ์ƒ๊น€
 */

์ง€๊ธˆ๊นŒ์ง€๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์™”๋‚˜?

//widget.h
class Widget_98
{
public:
  Widget_98();
  ~Widget_98();
private:
 ย struct Impl;  //๋‹จ์ˆœ ์„ ์–ธ๋งŒ , ์ด๋ ‡๊ฒŒ ์„ ์–ธ๋งŒ ํ•˜๊ณ  ์ •์˜๋Š” ํ•˜์ง€ ์•Š๋Š” ํ˜•์‹์„ ๋ถˆ์™„์ „ ํ˜•์‹(imcomplete type)์ด๋ผ๊ณ  ํ•œ๋‹ค.
 ย Impl *pImpl;
 };
 
 /** widget.h ์—์„œ ์—ฌ๋Ÿฌ ํ•ด๋”๋ฅผ ํฌํ•จํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.*/
 
 //widget.cpp
 #include "widget.h"
 #include "gadget.h"
 #include <string>
 #include <vector>

struct Widget_98::Impl { //์ •์˜
 ย std::string name;
  std::vector<double> data;
  Gadget g1, g2, g3;
  };
  
Widget_98::Widget_98()ย : pImpl(new Impl){}
Widget_98::~Widget_98() {delete pImpl;}

ย /** ๊ตฌํ˜„๋ถ€์—์„œ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ include,  ์˜์กด์„ฑ์ด .h์—์„œ .cpp๋กœ ์˜ฎ๊ฒจ์กŒ๋‹ค.*/

๊ฐœ์„ ํ• ์ ?

raw ํฌ์ธํ„ฐ ์‚ฌ์šฉ ํ•˜๋Š”๊ฒƒ new & delete ํ˜ธ์ถœ์ด ์›์‹œ ์‹œ์ ์ด๋‹ค. 'Widget ์ƒ์„ฑ์ž์—์„œ Widget::Impl๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•˜๊ณ  Widget์ด ํŒŒ๊ดด๋  ๋•Œ ๊ทธ ๊ฐ์ฒด๋ฅผ ํ•ด์ œ ํ•ด์ค˜์•ผํ•œ๋‹ค'๋Š” ๊ด€์ ์—์„œ std::unique_ptr(ํด๋ž˜์Šค ๋…์ ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ)์„ ์จ์•ผํ•œ๋‹ค. ๋ผ๊ณ  ์ €์ž๊ฐ€ ์ฃผ์žฅ.. ์™€๋‹ฟ์ง€๋Š” ์•Š๋Š”๋‹ค...

// widget.h
#include <memory>ย  
class Widget
{
public:
  Widget();
  //~Widget();ย ย //์†Œ๋ฉธ์ž ์ œ๊ฑฐ
private:
  struct Impl;
 ย std::unique_ptr<Impl> pImpl; ย //์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ž
};

// widget.cpp
...
//ํ•ญ๋ชฉ 21์— ๋”ฐ๋ผ make_unique ์‚ฌ์šฉ
Widget::Widget()ย : pImpl(std::make_unique<Impl>()){}
....

int main()
{
Widget w; //์—ฌ๊ธฐ์„œ ์—๋Ÿฌ๊ฐ€ ๋‚˜์•ผํ•˜๋Š”๋ฐ visual c++ 2017์—์„œ ์•ˆ๋‚˜๋„ค?
return 0;
}

์ž๋™์ƒ์„ฑ๋˜๋Š” ์†Œ๋ฉธ์ž์ฝ”๋“œ์—์„œ unique_ptr์ด delete๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ๋ถˆ์™„์ „ ํ˜•์‹์„ ์ฒดํฌ (static_asser)ํ•œ๋‹ค.

//std::unique_ptr <Widget::Impl>๋ฅผ ํŒŒ๊ดดํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ์‹œ์ ์— Widget::Impl์ด ์™„์ „ํ•œ ํ˜•์‹์ด๋˜๊ฒŒ ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ

//์œ„ ์ฝ”๋“œ์—์„œ widget.h์—
class Widget{
public:
  Widget();
  ~Widget();ย ย //์„ ์–ธ๋งŒ
  ...
};


//widget.cpp์— 
Widget::~Widget(){}ย //์†Œ๋ฉธ์ž ์ •์˜

//์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Widget::Impl์ด ์ •์˜๋˜์–ด ์žˆ์–ด ์™„์ „ํ•œ ํ˜•์‹์ด ๋œํ›„ Widget์ด ์„ ์–ธ๋˜์—ˆ๋‹ค.

๊ตฌํ˜„ํŒŒ์ผ์— ์†Œ๋ฉธ์ž๋ฅผ ์„ ์–ธํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ•์กฐํ•˜๋Š” ์šฉ๋„๋กœ

Widget::~Widget() = default;

##์ฃผ์˜ ํ• ์ ? ์†Œ๋ฉธ์ž๋ฅผ ์ •์˜ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋™์—ฐ์‚ฐ์ด ๋””ํดํŠธ๋กœ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.์ด๋™์„ ์ง€์›ํ•˜๋ ค๋ฉด ์ง์ ‘ ์„ ์–ธํ•ด์•ผํ•œ๋‹ค.

class widget{
...
Widget(Widget&& rhs) = default;
Widget& operator=(Widget&& rhs) = default ;
//์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค์— ์„ ์–ธํ•˜๋ฉด ๋ ๊ฒƒ ๊ฐ™์ง€๋งŒ
//์ด๋™ ๋ฐฐ์ • ์—ฐ์‚ฐ์ž๋Š” pImpl์„ ์žฌ์ •์˜ ํ•˜๊ธฐ์ „์— pImpl์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋ฅผ ํŒŒ๊ดดํ•ด์•ผํ•˜๋Š”๋ฐ ์ด๋•Œ Impl์ด ๋ถˆ์™„์ „ ํƒ€์ž…์ด๋ผ์„œ ์—๋Ÿฌ
//์ด๋™ ์ƒ์„ฑ์ž๋Š” ์ด๋™์ƒ์„ฑ์ž ์•ˆ์—์„œ ์˜ˆ์™ธ๋ฐœ์ƒํ–ˆ์„๋•Œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ์ด๋•Œ pImpl๋ฅผ ํŒŒ๊ดดํ•˜๋ ค๋ฉด Impl์ด ์™„์ „ ํ˜•์‹์ด์–ด์•ผ ํ•œ๋‹ค.
//๋”ฐ๋ผ์„œ ์—๋Ÿฌ. ํ•˜์ง€๋งŒ visual c++ 2017์€ ์ž˜๋œ๋‹ค....ใ…กใ…ก
...
};

//ํ•ด๊ฒฐ๋ฒ•? ๋ถˆ์™„์ „ ํƒ€์ž…์„ ํ•ด๊ฒฐํ•ด์ค˜์•ผํ•œ๋‹ค..

//widget.h
class widget{
...
Widget(Widget&& rhs);ย ย ย ย //์—ฌ๊ธฐ์„ 
Widget& operator=(Widget&& rhs);ย //์„ ์–ธ
...
}

//Widget.cpp
struct Widget::Impl {ย std::string name;ย std::vector<double> data;ย Gadget g1, g2, g3;};
Widget::Widget()ย : pImpl(std::make_unique<Impl>()){}
Widget::~Widget() = default;
Widget::Widget(Widget&& rhs) = default;ย ย ย ย ย //์—ฌ๊ธฐ์„œ
Widget&ย  Widget::operator=(Widget&& rhs) = default;ย ย //์ •์˜
...

์ •๋ฆฌ1

์˜์กด์„ฑ์„ ์ค„์˜€์„๋ฟ ํด๋ž˜์Šค๊ฐ€ ๋ฐ”๋€Œ์ง„ ์•Š๋Š”๋‹ค.์‚ฌ์šฉํ•˜๋Š” ์ž๋ฃŒ ๋ฉค๋ฒ„๊ฐ€ ๋ณต์‚ฌ๊ฐ€ ๊ฐ€๋Šฅํ˜•์‹์ด๋ผ๋ฉด widget์—ญ์‹œ ๋ณต์‚ฌ๋ฅผ ์ง€์›ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ณต์‚ฌ ์—ฐ์‚ฐ์€ ์ง์ ‘ ์ •์˜ ํ•ด์ค˜์•ผํ•œ๋‹ค. ์ด์œ 1) std:unique_ptr๊ฐ™์€ ์ด๋™ ์ „์šฉ ํ˜•์‹์ด ์žˆ๋Š” ํด๋ž˜์Šค์— ๋Œ€ํ•ด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ณต์‚ฌ ์—ฐ์‚ฐ์„ ๋งŒ๋“ค์–ด์ฃผ์ง€ ์•Š๋Š”๋‹ค. ์ด์œ 2) deep copy๋ฅผ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ.

์ •๋ฆฌ2

๋…์ ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ std:unique_ptr์„ ์‚ฌ์šฉํ•œ๋‹ค. ์†Œ๋ฉธ,์ด๋™ ์—ฐ์‚ฐ์‹œ ๋ถˆ์™„์ „ ํƒ€์ž…์„ ํ•ด๊ฒฐํ•ด์ค˜์•ผํ•œ๋‹ค.

์ฐธ๊ณ ํ• ์ 

๋…์ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ std::shared_ptr๋กœ ๊ตฌํ˜„ํ•œ๊ฒฝ์šฐ ์†Œ๋ฉธ,์ด๋™ ์—ฐ์‚ฐ์„ ๋”ฐ๋กœ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž‘์„ฑํ•œ ํŠน์ˆ˜ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋“ค์ด ์“ฐ์ด๋Š” ์‹œ์ ์—์„œ ํ”ผ์ง€์นญ ํ˜•์‹๋“ค์ด ์™„์ „ํ•œ ํ˜•์‹์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ์š”๊ตฌ ์กฐ๊ฑด์ด ์‚ฌ๋ผ์ง„๋‹ค.(์†Œ๋ฉธ,์ด๋™ ์—ฐ์‚ฐ์—์„œ ๊ฒฐ๊ตญ delete์‹œ static_assert์ฒดํฌ๊ฐ€ ์—†๋‚˜?)