---
# System prepended metadata

title: unique_ptr のconstとは？
tags: [elkurin-daily-note, C++-General]

---

# unique_ptr のconstとは？
[unique_ptr](https://cpprefjp.github.io/reference/memory/unique_ptr.html) にconst修飾子がついているケースがChromiumでも散見される。
```cpp=
const std::unique_ptr<viz::CompositorRenderPass>& render_pass =
    frame.render_pass_list.back();
```
constがつくとどういう挙動になるのかを確認する。

## そもそもconstとは
constは変数前につけることでその変数の値を不変にする修飾子。  
例えば`const int val = 0`と変数`val`を宣言すると違う値を再代入することはできない。  
`val = 1`とかいたらコンパイルエラーになる。

constはポインタにつけると挙動がややこしくなる。  
ポインタ変数は、指すアドレスそのものを変更できるかと、指す先の値を変更できるかの2タイプ存在する。  
それはconstをつける位置によって変わる。

```cpp=
// 値の場合const intとint constは同じ
const int val1 = 0;
// val1 = 1;  <- コンパイルエラー

int const val1 = 0;
// val2 = 1;  <- コンパイルエラー

// ポインタの場合constとint*のどちらを先に書くかで変わる
int val = 0;

const int* ptr1 = &val;
ptr1 = nullptr; // <- OK
// *ptr1 = 1; <- コンパイルエラー

int* const ptr2 = &val;
// ptr2 = nullptr; <- コンパイルエラー
*ptr2 = 1; // <- OK

// どちらもつけることもできる。その場合どちらも制約がつく
const int* const ptr3 = &val;
// ptr3 = nullptr; <- コンパイルエラー
// *ptr3 = 1;      <- コンパイルエラー
```

## std::unique_ptrの場合
ではstd::unique_ptrとconstの関係を見る。  
まず先頭にconstをつけてみる。
```cpp=
const std::unique_ptr<int> uptr1 = std::make_unique<int>(0);
// uptr1 = nullptr; <- コンパイルエラー
*uptr1 = 1; // <- OK
```
生ポインタにおける`int* const ptr2`と同じ挙動をした。  
では`const int*`にあたる書き方はどうすればいいかというと以下。
```cpp=
std::unique_ptr<const int> uptr2 = std::make_unique<const int>(0);
uptr2 = nullptr; // OK
// *uptr2 = 1; <- コンパイルエラー
```
格納する値をconstにすればよい。

生ポインタと同様に、どちらも不変にすることもできる。
```cpp=
const std::unique_ptr<const int> uptr3 = std:make_unique<const int>(0);
// uptr3 = nullptr;
// *uptr3 = 1;
```

const auto みたいに書けば良かった…

## Note: std::unique_ptrのconst参照渡し？
関数にconst参照渡しをする場合、その関数内で引数の値を書き換えられないことを期待している。  
std::unique_ptrの先頭にconstをつけても格納されている値は書き換えられてしまうので要注意。  
値を取り出してconst参照で渡すのが一番よさそう？
```cpp=
void Func(const A& a);

auto a = std::make_unique<A>();
Func(*a);
```
