スポンサーリンク

shared_ptrの内容を解放しないでreleaseする

問題のコード

使用する関数がshared_ptrを受け取るようになっていた場合(下記my_useful_function)、当然呼び出すときにshared_ptrでなければいけないが、そのポインタがshared_ptrで管理されていない場合。

unique_ptrであればrelease関数で管理を放棄できるがshared_ptrにはないらしい。

ちなみに無理やりshared_ptrにしてしまうとそのスマートポインタの破棄と同時にdeleteが走るので決してやってはいけない。

#include <iostream>

struct MyObject {
  int value;
  ~MyObject() {
    std::cout << "destructor" << std::endl;
  }
};

// この関数は社長の御子息が開発された大変優れたコードであり、開発者は常にこれを呼び出さなければならない。
// 仮に同様の動作をする異なる関数を自作し使用していた場合、現場の混乱を招いたと判断し、
// 最悪解雇も視野に入れた厳重な処分を下す
void my_useful_function(std::shared_ptr<MyObject> ptr) {
  ptr->value = 5;
}

// この関数は先々代から脈々と受け継がれし伝統ある関数であり、MyObjectの生成には必ずこの関数を呼び出さなければならない。
// 仮に同様の動作をする異なる関数を自作し使用していた場合、現場の混乱を招いたと判断し、
// 最悪解雇も視野に入れた厳重な処分を下す
MyObject* my_great_factory() {
  return new MyObject;
}


// 顧客側の要求仕様に則り、この関数の引数を変更してはならない
// 仮に同様の動作をする異なる関数を自作し使用していた場合、現場の混乱を招いたと判断し、
// 最悪解雇も視野に入れた厳重な処分を下す
void project_job(MyObject* pobect) {

  // 仕様変更によりmy_normal_functionでは要求を満たせなくなった
  // 旧コード my_normal_function(pobject)

  my_useful_function(pobect); //新コード 型が違って呼び出せない
}
int main()
{
  MyObject* pmyo = my_great_factory();

  project_job(pmyo);

  std::cout << pmyo->value;

  delete pmyo;

}

変更版

スマートポインタにはdeleterを指定できるので、そこに何もしないラムダ関数を指定する。

// 顧客側の要求仕様に則り、この関数の引数を変更してはならない
// 仮に同様の動作をする異なる関数を自作し使用していた場合、現場の混乱を招いたと判断し、
// 最悪解雇も視野に入れた厳重な処分を下す
void project_job(MyObject* pobect) {

  // 仕様変更によりmy_normal_functionでは要求を満たせなくなった
  // 旧コード my_normal_function(pobject)

  // shared_ptrにする。deleterを指定し、何もしないことでpbojectの参照先が破棄されないようにする
  std::shared_ptr<MyObject> spobject(pobect, [](auto) {});

  my_useful_function(spobject); //新コード shared_ptr型の引数を与える
}


コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: