Skip to main content
added 288 characters in body
Source Link
Philipp
  • 140
  • 6

Often you can use a pattern like this:

class C {
public:
  void foo() {
    underlying_foo(handle.get());
  }

  void bar() {
    // transfers ownership
    underlying_bar(handle.release());
  }

  // use default copy/move constructor and assignment operator

private:
  struct deleter {
    void operator()(T* ptr) {
      deleter_fn(ptr);
    }
  };
  std::unique_ptr<T, deleter> handle;
};

By using release you can explicitly transfer ownership. However this is confusing and you should avoid it if at all possible.

Most C libraries have a C++-like object life cycle (object allocation, accessors, destruction) that maps nicely onto the C++ pattern without ownership transfer.

If users need shared ownership, they should use shared_ptr with your classes. Don't try to implement any ownership sharing yourself.


Update: If you want to make the transfer of ownership more explicit, you can use a reference qualifier:

void bar() && { ... }

Then users must call bar on lvalues like this:

C o;
std::move(o).bar();  // transfer of ownership is explicit at call site

Often you can use a pattern like this:

class C {
public:
  void foo() {
    underlying_foo(handle.get());
  }

  void bar() {
    // transfers ownership
    underlying_bar(handle.release());
  }

  // use default copy/move constructor and assignment operator

private:
  struct deleter {
    operator()(T* ptr) {
      deleter_fn(ptr);
    }
  };
  std::unique_ptr<T, deleter> handle;
};

By using release you can explicitly transfer ownership. However this is confusing and you should avoid it if at all possible.

Most C libraries have a C++-like object life cycle (object allocation, accessors, destruction) that maps nicely onto the C++ pattern without ownership transfer.

If users need shared ownership, they should use shared_ptr with your classes. Don't try to implement any ownership sharing yourself.

Often you can use a pattern like this:

class C {
public:
  void foo() {
    underlying_foo(handle.get());
  }

  void bar() {
    // transfers ownership
    underlying_bar(handle.release());
  }

  // use default copy/move constructor and assignment operator

private:
  struct deleter {
    void operator()(T* ptr) {
      deleter_fn(ptr);
    }
  };
  std::unique_ptr<T, deleter> handle;
};

By using release you can explicitly transfer ownership. However this is confusing and you should avoid it if at all possible.

Most C libraries have a C++-like object life cycle (object allocation, accessors, destruction) that maps nicely onto the C++ pattern without ownership transfer.

If users need shared ownership, they should use shared_ptr with your classes. Don't try to implement any ownership sharing yourself.


Update: If you want to make the transfer of ownership more explicit, you can use a reference qualifier:

void bar() && { ... }

Then users must call bar on lvalues like this:

C o;
std::move(o).bar();  // transfer of ownership is explicit at call site
Source Link
Philipp
  • 140
  • 6

Often you can use a pattern like this:

class C {
public:
  void foo() {
    underlying_foo(handle.get());
  }

  void bar() {
    // transfers ownership
    underlying_bar(handle.release());
  }

  // use default copy/move constructor and assignment operator

private:
  struct deleter {
    operator()(T* ptr) {
      deleter_fn(ptr);
    }
  };
  std::unique_ptr<T, deleter> handle;
};

By using release you can explicitly transfer ownership. However this is confusing and you should avoid it if at all possible.

Most C libraries have a C++-like object life cycle (object allocation, accessors, destruction) that maps nicely onto the C++ pattern without ownership transfer.

If users need shared ownership, they should use shared_ptr with your classes. Don't try to implement any ownership sharing yourself.