mirror of
https://github.com/pybind/pybind11.git
synced 2026-04-19 22:39:09 +00:00
Reimplement py::init<...> to use common factory code
This reimplements the py::init<...> implementations using the various functions added to support `py::init(...)`, and moves the implementing structs into `detail/init.h` from `pybind11.h`. It doesn't simply use a factory directly, as this is a very common case and implementation without an extra lambda call is a small but useful optimization. This, combined with the previous lazy initialization, also avoids needing placement new for `py::init<...>()` construction: such construction now occurs via an ordinary `new Type(...)`. A consequence of this is that it also fixes a potential bug when using multiple inheritance from Python: it was very easy to write classes that double-initialize an existing instance which had the potential to leak for non-pod classes. With the new implementation, an attempt to call `__init__` on an already-initialized object is now ignored. (This was already done in the previous commit for factory constructors). This change exposed a few warnings (fixed here) from deleting a pointer to a base class with virtual functions but without a virtual destructor. These look like legitimate warnings that we shouldn't suppress; this adds virtual destructors to the appropriate classes.
This commit is contained in:
@@ -274,8 +274,9 @@ TEST_SUBMODULE(factory_constructors, m) {
|
||||
}
|
||||
int i;
|
||||
};
|
||||
// Workaround for a `py::init<args>` on a class without placement new support
|
||||
// As of 2.2, `py::init<args>` no longer requires placement new
|
||||
py::class_<NoPlacementNew>(m, "NoPlacementNew")
|
||||
.def(py::init<int>())
|
||||
.def(py::init([]() { return new NoPlacementNew(100); }))
|
||||
.def_readwrite("i", &NoPlacementNew::i)
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user