개요
PIMPL(Pointer to Implementation)은 컴파일 방화벽으로 사용하는 코딩 관용구로 헤더 파일 하나를 수정했을 때 많은 소스 파일이 재 컴파일하지 않게 해주는 메커니즘이다. 1990년대 C++ 이 사춘기를 보내던 시절에는 PIMPL 관용구의 사용이 정당화되었는데 현재는 PIMPL을 사용할 필요가 거의 없다. 현재 컴파일하는 데 걸리는 시간은 1990년대에 걸렸던 시간의 1%에 불과하기 때문이며 BigClass를 깨서 조금 더 초점을 맞춘 인터페이스를 제공하는 방법이 PIMPL을 구현하는 방법만큼 효율적일 수 있다. [1]
PIMPL 소스코드
PIMPL을 사용하지 않는 코드는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
|
#pragma once
#include<vector>
#include<string>
class Test {
public:
std::vector<std::string> s;
};
|
이 코드의 문제점은 Vector와 String 헤더 파일에 의존성이 생겨서 헤더파일에 변경이 생기면 재컴파일 해야하는 문제가 있다. 이 코드를 PIMPL 패턴을 사용해서 바꾸면 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#pragma once
#include<memory> //스마트 포인터
class Pimpl; //전방선언
class Test {
public:
std::shared_ptr<Pimpl> pimpl_;
Test();
void PrintString();
};
|
먼저 헤더파일에 Vector와 String 헤더 파일을 지우고 Pimpl이라는 클래스를 전방 선언 후 C++11 표준에 있는 스마트 포인터인 Shared_ptr을 사용한다 Unique_ptr은 다른 조치를 좀 해줘야 작동한다. 자세한 내용은( Effective Modern C++(인사이트) 책에 소개가 나와있다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#include<vector>
#include<string>
#include<iostream>
#include"Pimpl.h" //Test Class 헤더파일
//Pimpl Class 정의
class Pimpl {
public:
std::vector<std::string>s;
};
Test::Test():pimpl_(std::make_shared<Pimpl>()) {
std::string temp = "HELLO WORLD!\n";
pimpl_->s.emplace_back(temp);
pimpl_->s.emplace_back(temp);
pimpl_->s.emplace_back(temp);
}
void Test::PrintString() {
for (const auto& i : pimpl_->s) {
std::cout << i;
}
}
int main() {
Test t;
t.PrintString();
}
|
그 후에 Pimpl 클래스를 구현부(CPP)에서 작성 후 다음과 같이 사용하면 컴파일 의존성을 줄일 수 있다. 이 외에도 구현부와 선언부가 나뉜다는 장점도 존재한다.
후기
현재 A* 알고리즘을 이용한 프로젝트에 PIMPL 패턴을 사용해서 작성을 하고 있는데 C++최적화 책에서 사용해봐야 별 의미가 없다는 말을 듣고 글을 간단하게 작성하였다. 사용이 어려운 패턴도 아니고 이 정도 예시만 봐도 충분히 구현이 가능하기 때문에 짧게 작성했다
내가 생각하는 이 패턴의 단점은 구현부가 좀 더러워지는 단점이 있고 책에서 말하기에는 인라인 될 수 있는 class의 멤버 함수는 호출하는 코드가 필요합니다?(번역이 좀 이상한 거 같은데) 이러한 단점이 있다고 한다.
지금 작성하는 프로젝트에 PIMPL을 빼야할지 고민이며 이러한 패턴이 있다는 정도만 알면 도움이 될 거 같다.
출처
[1] [커트 컨서로스] [C++최적화]: 한빛미디어
'프로그래밍 > Modern C++' 카테고리의 다른 글
[C++] 메모리 풀(Memory Pool) (2) | 2020.09.25 |
---|---|
[C++] 기본 객체지향 특징 정리 (0) | 2020.09.18 |
[C++] 멤버 함수를 Thread에 등록하는 방법 (0) | 2020.07.14 |
[C++] private 함수보다는 delete 를 사용하자 (0) | 2020.06.28 |
[C++] RAII(Resoucre Acquisition Is Initialization) (0) | 2020.06.20 |