> [!date] published: 2022-12-23
## 🌟 explicit specifier
### ✨ explicit specifier
원치 않는 형변환이 일어나지 않게 하는 지정자 (specifier)
C++11 키워드 인 줄 알고 흐린눈했었는데 알고보니 생성자에는 (무조건?) explicit 키워드를 붙여줘야 C++98에 맞는 문법이었다.
`explicit` 지정자가 붙은 생성자는 “명백함”을 표현한다. 이 “명백함”이라는 것은 암시적 형변환과 복사 초기화 (Copy initialization)에 사용되지 않음을 의미한다.
`explicit` 지정자 없이 정의된 생성자는 Converting Constructor라고 하고, C++11부터 지원하고, 이 생성자는 복사 초기화에도 이용될 수 있다.
[explicit specifier - cppreference.com](https://en.cppreference.com/w/cpp/language/explicit)
[Converting constructor - cppreference.com](https://en.cppreference.com/w/cpp/language/converting_constructor)
```cpp
struct A
{
A() { } // converting constructor (since C++11)
A(int) { } // converting constructor
A(int, int) { } // converting constructor (since C++11)
};
struct B
{
explicit B() { }
explicit B(int) { }
explicit B(int, int) { }
};
int main()
{
A a1 = 1; // OK: copy-initialization selects A::A(int)
A a2(2); // OK: direct-initialization selects A::A(int)
A a3{4, 5}; // OK: direct-list-initialization selects A::A(int, int)
A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
A a5 = (A)1; // OK: explicit cast performs static_cast, direct-initialization
// B b1 = 1; // error: copy-initialization does not consider B::B(int)
B b2(2); // OK: direct-initialization selects B::B(int)
B b3{4, 5}; // OK: direct-list-initialization selects B::B(int, int)
// B b4 = {4, 5}; // error: copy-list-initialization selected an explicit constructor
// B::B(int, int)
B b5 = (B)1; // OK: explicit cast performs static_cast, direct-initialization
B b6; // OK, default-initialization
B b7{}; // OK, direct-list-initialization
// B b8 = {}; // error: copy-list-initialization selected an explicit constructor
// B::B()
}
```
### ✨ copy-initialization vs direct-initialization
[c++ - Is there a difference between copy-initialization and direct-initialization? - Stack Overflow](https://stackoverflow.com/questions/1051379/is-there-a-difference-between-copy-initialization-and-direct-initialization)
[01.11. C++ \| 변수 초기화 3가지 방법과 차이](https://heroine-day.tistory.com/20)
```cpp
struct B;
struct A {
operator B();
};
struct B {
B() { }
B(A const&) { std::cout << "<direct> "; }
};
A::operator B() { std::cout << "<copy> "; return B(); }
int main() {
A a;
B b1(a); // 1)
B b2 = a; // 2)
}
// output: <direct> <copy>
```
1. b의 생성자를 바로 호출해서 b1을 생성할 수 있다.
2. a가 B타입이 아니기 때문에 “변환”이 필요하다.
→ `explicit` 키워드가 없는 경우에는 변환되어 초기화를 할 수 있고,
→ `explicit` 키워드가 있는 경우에는 변환되어 초기화를 할 수 없다.
C++ 11 이전에는 성능 개선을 이유로 직접 초기화가 권장되었다고 한다.
## 🌟 allocator
### ✨ allocator
Standard Library의 특정 부분에서 사용되는 메모리 모델을 정의하기 위한 클래스이다.
커스텀 allocator를 만들 수도 있는 것 같은데, 일단은 기본적인 allocator template에 대해서만 공부했다.
[cplusplus.com/reference/memory/allocator/](https://cplusplus.com/reference/memory/allocator/)
[std\:\:allocator - cppreference.com](https://en.cppreference.com/w/cpp/memory/allocator)
```cpp
/*
std::allocator::address
- return the actual address of x
*/
pointer address( reference x ) const;
const_pointer address( const_reference x ) const;
/*
std::allocator<T>::allocate
- allocate n * sizeof(T) bytes memory that are not initialized
- return pointer to the first element of array
- throw std::bad_alloc if allocation fails
*/
pointer allocate( size_type n, const void * hint = 0 );
/*
std::allocator<T>::deallocate
- deallocates the storage referenced by the pointer p.
- p는 반드시 전에 allocate() 함수로 얻어진 포인터여야 한다.
- n은 반드시 전에 p를 얻기 위해 호출한 allocate() 함수의 인자 속 n과 동일해야 한다.
*/
void deallocate( T* p, std::size_t n );
/*
std::allocator<T>::max_size
- allocator(n, 0)을 성공적으로 호출할 수 있는 가장 큰 n 반환.
- 대부분 std::numeric_limits<size_type>::max() / sizeof(value_type)
*/
size_type max_size() const throw();
/*
std::allocator::construct
- p가 가리키는 지점에 객체 생성
- 메모리를 할당하지는 않기 때문에 p가 가리키는 지점은 사용가능한 메모리 공간이어야 한다.
*/
void construct ( pointer p, const_reference val );
/*
std::allocator::destroy
- p가 가리키는 지점의 객체를 파괴
- 메모리를 해제하는 것이 아니므로 반드시 이후에 deallocate 과정이 필요함.
- 같은 맥락에서 construct 이후에 destory를 하지 않고 deallocate를 한다면? 안될 것 같음.
*/
void destroy (pointer p);
```
### ✨ allocator vs new / delete
[memory - C++ STL allocator vs operator new - Stack Overflow](https://stackoverflow.com/questions/5628059/c-stl-allocator-vs-operator-new)
allocator는 STL에서 메모리 관리를 위해서 사용하는 클래스라고 했다.
결론적으로는 allocator를 사용했을 때에는 좀 더 세부적인 제어 수준을 가질 수 있다는 차이가 있었다.