I am having a strange problem instantiating a structure living inside a class, where in construction it calls the destructor (several times) and even calls the parent object destructor.
Class with structure:
class Model {
public:
struct StepModelIO {
StepModelIO(Model model, ...) {DoConstruction(Model model, ...);}
StepModelIO(const StepModelIO &other) {DoConstruction(Model model, ...); }
~StepModelIO() {}
DoConstruction() {
...
}
}
Model(...) {
...
}
Model(const Model &other) {DoConstruction(...);}
~Model() {
...
}
private:
DoConstruction(...) {
}
}
Calling function:
void main() {
Model::StepModelIO stepArgs = Model::StepModelIO(...);
}
The resulting set of calls, with 'object' being the StepModelIO and 'parent' being the Model:
Construct parent w/ copy constructor
Construct object
Destruct parent
Construct object w/ copy constructor
Construct parent w/ copy constructor
Construct object
Destruct parent
Destruct object
Destruct object (again...)
Destruct parent
Unsurprisingly the resulting structure (a StepModelIO) is not in a good state after this all happens, and the path seemed ridiculous. I have the structure housed like this to use the same generic at the parent Model object, which may explain some of the issues.
I have tried (perhaps naively) to use the 'rule of three' on constructors and destructors, it's possible I've munged this up badly.
Edit: Full code
template<typename U, typename V>
class Model{
public:
struct StepModelIO {
Model<U, V> model;
U u;
V v;
StepModelIO() {}
StepModelIO(Model<U, V> model, U u, V v) {
this->model = model;
this->u = u;
this->v = v;
}
StepModelIO (const StepModelIO &other) {
StepModelIO(other.model, other.u, other.v);
}
~StepModelIO() {
}
};
Model(char * libraryPath) {DoConstruction(libraryPath);}
Model() {}
Model (const Model &other) {
DoConstruction(other.m_LibraryPath);
}
~Model() {
this->Stop();
}
void Init() {
if (!this->m_Initialised) {
this->ModelInit();
m_Initialised = true;
}
}
void Stop() {
if (this->m_Initialised) {
this->ModelStop();
m_Initialised = false;
}
}
void Restart() {
this->ModelRestart();
}
void Step(U u, V v) {
ModelStep(u, v);
}
private:
char* m_LibraryPath;
HINSTANCE m_ModelDLL;
bool m_Initialised;
typedef int (__cdecl * EmptyModelFunctionPointer)(); // Interpret integer as C code pointer named 'EmptyModelFunctionPointer'
typedef int (__cdecl * ModelFunctionPointer)(U u, V v);
EmptyModelFunctionPointer ModelInit;
EmptyModelFunctionPointer ModelStop;
EmptyModelFunctionPointer ModelRestart;
ModelFunctionPointer ModelStep;
virtual void DoConstruction(char * libraryPath){
this->m_Initialised = false;
this->m_LibraryPath = libraryPath;
this->m_ModelDLL = LoadLibrary(libraryPath);
this->ModelInit = GetFunction<EmptyModelFunctionPointer>(m_ModelDLL, "Init");
this->ModelStop = GetFunction<EmptyModelFunctionPointer>(m_ModelDLL, "Stop");
this->ModelRestart = GetFunction<EmptyModelFunctionPointer>(m_ModelDLL, "Restart");
this->ModelStep = GetFunction<ModelFunctionPointer>(m_ModelDLL, "Step");
}
template<typename pointerType>
pointerType GetFunction(HINSTANCE modelLibrary, char * functionName){
return (pointerType)GetProcAddress(HMODULE (modelLibrary),functionName);
}
};
Caller:
StepModelIO<Type_1*, Type_2*> stepArgs = StepModelIO<Type_1*, Type_2*>(newModel, &a, &b[0]);
You're passing things by value, which will result in temporary objects being constructed and destructed. Pass them by const reference instead.
change
StepModelIO(Model model, ...)
to
StepModelIO(const Model &model, ...)
You've now changed the code. So you really want this, I think.
StepModelIO(const Model<U, V> &model, const U &u, const V &v)
I have notices tat inside the class StepModelIO you have a member Model<U, V> model; so for each instance of class StepModelIO the destructor of model will be caled also; first ~StepModelIO() and second ~Model<U, V>()
so given the code you provided:
Model::StepModelIO stepArgs = Model::StepModelIO(...);
This has two objects of the type StepModelIO. One is the on in the right (rvalue) and the second one is stepArgs.
First the destructor for the one in the right is called resulting in:
1:Destruct StepModelIO
2:Destruct Model
And when the destruction of stepArgs occurs :
3:Destruct StepModelIO
4:Destruct Model
Related
I have written a little game engine in c++ and it works ok but is not the best performance wise. I also learned a lot and I want to redo it now. But last time I heavily used shared_ptr for classes like gui textures and model wrappers (that hold i.e. the 3d position and the opengl vao). I've heared that shared_ptr should not really be used, but I dont really know how to do it any other way. Here's the pseudo-code-like layout:
This code is not complete or working but I want to share the idea of my layout
// d3 stands for 3d
class D3Model {
VAO vao;
bool useBloom;
unsigned int texture;
// ... and so on
static std::vector<std::shared_ptr<D3Model>> models; // current idea, approach 1
static std::vector<D3Model> models1; // different approach (2)
D3Model() {
models.push_back(shared_from_this()); // app.1
models1.push_back(*this);
}
}
// main file
int main() {
std::shared_ptr<D3Model> model = std::make_shared<D3Model>();
model->setTexture(0); // ignore the non sense content
D3Model model1;
model1.setTexture(0); // would not get updated in the vector
while(true) {
model->increaseRotation(1);
model1.increaseRotation(1);
Renderer::render();
}
}
// different file
class Renderer {
static void render() {
for(const auto& all : D3Model::models) {
// render model
}
for(const auto& all : D3Model::models1) {
// render model1, would not have increased rotation
}
}
}
For more clarification, imagine the following use of the engine:
After hitting play on a start screen, the engine loads some 3d models from files and stores them. One of them gets rotated every frame and every one of them gets rendered. Maybe some other models must be loaded after because of a change in gameplay (Player joined...). Then they all get deleted when the user returns to the main menu. My problem with approach 2 is that I'd have to update the vector everytime the rotation of the model is increased, whereas that would automatically be handled with approach 1. However, I have heared that shared_ptr is bad for performance.
Is shared_ptr for this case the best solution or should I just use normal objects? But my problem with that is how would I apply changes to the object (the setTexture for example) without having to update the vector content. And raw pointers arent really good either. How is something like that done?
Thanks, unreal
Ok you can create yor own RefCouner class like me:
/// RefCounter.hpp
#pragma once
class RefCounter {
public:
RefCounter();
RefCounter(const RefCounter&);
RefCounter& operator=(const RefCounter&);
void grab();
usize reference() const;
bool release();
protected:
virtual void finalize();
virtual ~RefCounter();
private:
usize _reference;
};
template<typename T>
struct ref {
inline ref() : class_ptr (nullptr) {}
inline ref(T* obj) : class_ptr (obj) { if(class_ptr) class_ptr->grab(); }
inline ref(const ref& other) : class_ptr (other.class_ptr) { if(class_ptr) class_ptr->grab(); }
inline ref& operator=(T* obj) {
if(obj)
obj->grab();
if(class_ptr)
class_ptr->release();
class_ptr = obj;
return *this;
}
inline ref& operator=(const ref& other){
T* obj = other.class_ptr;
if(obj)
obj->grab();
if(class_ptr)
class_ptr->release();
class_ptr = obj;
return *this;
}
T* get() const {
return class_ptr;
}
operator T*() const {
return class_ptr;
}
T* operator->() const {
return class_ptr;
}
inline ~ref() {
if(class_ptr)
class_ptr->release();
}
private:
T* class_ptr;
};
/// RefCounter.cpp
RefCounter::RefCounter() : _reference(0){
}
RefCounter::RefCounter(const RefCounter&) : _reference(0) {
}
RefCounter& RefCounter::operator=(const RefCounter&) {
return *this;
}
void RefCounter::grab() {
_reference++;
}
usize RefCounter::reference() const {
return _reference;
}
bool RefCounter::release() {
if(_reference > 1) {
_reference--;
return false;
} else {
_reference = 0;
finalize();
return true;
}
}
void RefCounter::finalize() {
delete this;
}
RefCounter::~RefCounter() {
}
I'd like to wrap all usages of a class instance with a mutex. Today I have
std::map<int, std::shared_ptr<MyClass>> classes;
and functions to find and return instances, like:
std::shared_ptr<MyClass> GetClass(int i);
I'd like to ensure that GetClass() can only retrieve an instance if someone else hasn't already retrieved it, with some RAII mechanism. Usage would be like:
void CallingFunction()
{
auto c = GetClass(i); // mutex for class id 'i' is acquired here
// some calls to class
c.SomeFunction();
} // mutex is released here when 'c' goes out of scope
With the mutex acquired by CallingFunction() other threads that wanted to access the same class instance would block on their calls to GetClass().
I've been looking at a few ways of doing it, such as with a wrapper class like:
class ClassContainer
{
public:
std::shared_ptr<Class> c;
std::mutex m;
};
Where I'd modify GetClass() to be:
ClassContainer GetClass(int i);
But I'm having trouble figuring out both where the std::mutex should be kept, I tried initially storing it in the map before moving to using a container class like:
std::map<int, std::pair<std::mutex, std::shared_ptr<MyClass<>>> classes;
but that wasn't working well, now with the ClassContainer how to have ClassContainer lock the std::mutex like std::lock_guard<> when the caller acquires one via a call to GetClass().
I've been looking at a few ways of doing it, such as with a wrapper class like:
Yes this is proper way to do it and you are close, but you cannot keep mutex itself in this class, only locker. And std::unique_lock is a proper type for that as it has necessary move ctor etc. I would make fields private though and create necessary accessors:
class ClassContainer
{
std::shared_ptr<Class> c;
std::uniqe_lock<mutex> lock;
public:
ClassContainer( std::pair<std::mutex,std::shared_ptr<Class>> &p ) :
c( p.second ),
lock( p.first )
{
}
Class * operator->()const { return c.get(); }
Class & operator*() const { return *c; }
};
then usage is simple:
void CallingFunction()
{
auto c = GetClass(i); // mutex for class id 'i' is acquired here
// some calls to class
c->SomeFunction();
// or even
GetClass(i)->SomeFunction();
}
It is Class which should hold the mutex, something like:
class Class
{
public:
// Your methods...
std::mutex& GetMutex() { return m; }
private:
std::mutex m;
};
class ClassContainer
{
public:
ClassContainer(std::shared_ptr<Class> c) :
c(std::move(c)),
l(this->c->GetMutex())
{}
ClassContainer(const ClassContainer&) = delete;
ClassContainer(ClassContainer&&) = delete;
ClassContainer& operator =(const ClassContainer&) = default;
ClassContainer& operator =(ClassContainer&&) = default;
// For transparent pointer like access to Class.
decltype(auto) operator -> () const { return c; }
decltype(auto) operator -> () { return c; }
const Class& operator*() const { return *c; }
Class& operator*() { return *c; }
private:
std::shared_ptr<Class> c;
std::lock_guard<std::mutex> l;
};
ClassContainer GetClass(int i)
{
auto c = std::make_shared<Class>();
return {c}; // syntax which avoids copy/move contructor.
}
and finally usage:
auto&& cc = GetClass(42); // `auto&&` or `const&` pre-C++17, simple auto possible in C++17
cc->ClassMethod();
Simplified demo.
Accidentally, I did something extremely similar recently (only I returned references to objects instead of shared_ptr. The code worked like following:
struct locked_queue {
locked_queue(locked_queue&& ) = default;
mutable std::unique_lock<decltype(queue::mutex)> lock;
const queue::q_impl_t& queue; // std::deque
};
And here is how it would be used:
locked_queue ClassX::get_queue(...) {
return {std::unique_lock<decltype(mutex)>{mutex}, queue_impl};
}
I have a class idx_aware that goes into a container container, which wraps around a std::vector. When the class is added to container, container sets a pointer to itself in idx_aware, as well as the index of idx_aware in its internal memory storage.
The index is not going to change until the container is destroyed or idx_aware is removed; idx_aware needs to know about its container and its index, because it has some methods that require both to work.
Now this introduces the following problem: when I get a non-const reference to an idx_aware class contained in container, I could assign to it another idx_aware class, which could have a different index. The intention would be assigning all the fields and keeping the index as it is.
#include <vector>
#include <limits>
#include <iostream>
class container;
// Stores a std::size_t field, which can be set only by subclasses.
class with_idx {
std::size_t _i;
public:
with_idx() : _i(std::numeric_limits<std::size_t>::max()) {}
operator std::size_t() const { return _i; }
protected:
void set_idx(std::size_t i) { _i = i; }
};
// Knows its index and its container
class idx_aware : public with_idx {
container const *_container;
int _some_field1;
float _some_field2;
public:
void foo() {
// Do stuff using _container and _i
}
private:
friend class container;
};
// Wraps around a std::vector
class container {
std::vector<idx_aware> _data;
public:
idx_aware &operator[](std::size_t idx) {
// Need non-const access to call foo
return _data[idx];
}
idx_aware const &operator[](std::size_t idx) const {
return _data[idx];
}
std::size_t add(idx_aware const &item) {
// Here it could potentially reuse a freed position
std::size_t free_slot = _data.size();
// Ensure _data is big enough to contain free_slot
if (_data.size() <= free_slot) {
_data.resize(free_slot + 1);
}
// Assign
_data[free_slot] = item;
_data[free_slot].set_idx(free_slot);
_data[free_slot]._container = this;
return free_slot;
}
};
int main() {
container c;
idx_aware an_item;
std::size_t i = c.add(an_item);
std::cout << c[i] << std::endl; // Prints 0
idx_aware another_item; // Created from somewhere else
// I want to set all the data in idx_aware, but the
// index should stay the same!
c[i] = another_item;
std::cout << c[i] << std::endl; // Prints numeric_limits<size_t>::max()
// Now container[i] is broken because it doesn't know anymore its index.
return 0;
}
One possible workaround would be to change with_idx in such a way that when set_idx is called, a flag is set that prevents assignment and copy operator to overwrite the _i property, like this:
class with_idx {
std::size_t _i;
bool _readonly;
public:
with_idx() : _i(std::numeric_limits<std::size_t>::max()), _readonly(false) {}
with_idx(with_idx const &other) : _i(other._i), _readonly(false) {}
with_idx &operator=(with_idx const &other) {
if (!_readonly) {
_i = other._i;
}
return *this;
}
operator std::size_t() const { return _i; }
protected:
void set_idx(std::size_t i) {
_i = i;
if (i != std::numeric_limits<std::size_t>::max()) {
// This has been set by someone with the right to do so,
// prevent overwriting
_readonly = true;
} else {
// Removed from the container, allow overwriting
_readonly = false;
}
}
};
This would have the consequence of returning, after assignment, a reference to an idx_aware class with unchanged index.
idx_aware ¬_in_container1 = /* ... */;
idx_aware ¬_in_container2 = /* ... */;
idx_aware &in_container = /* ... */;
not_in_container1 = in_container = not_in_container2;
// std::size_t(not_in_container_1) != std::size_t(not_in_container_2)
Is there a design pattern that can model this situation in a better way? My searches were not successful.
Are there other unwanted consequences of overriding the assignment operator in this way? The limitation I pointed out in the previous example does not look too "bad".
Is there an easier solution? I thought about writing some proxy object to replace the idx_aware & return type of operator[].
Experience tells that when C++ does not do what you intend, you are likely to be misusing OOP...
Robert's comment suggested me this solution.
Why would the contained object know about its container? To be able to perform actions such as foo and provide shorthand methods that otherwise would require to have access to the container.
Let's take this functionality away from the contained object; the contained object is just data payload. Instead, let's make operator[] return not the contained object, but some sort of iterator, a wrapper around the contained object, which knows the container and the index, and once dereferenced returns the actual contained object.
class was_idx_aware {
int _some_field1;
float _some_field2;
};
class container {
std::vector<idx_aware> _data;
public:
class idx_aware_wrapper {
container const *_container;
std::size_t _idx;
public:
idx_aware_wrapper(container const &c, std::size_t i)
: _container(&c)
, _idx(i)
{}
was_idx_aware const &operator*() const {
return _container->_data[_idx];
}
was_idx_aware &operator*() {
return _container->_data[_idx];
}
void foo() {
// Do stuff using _container and _idx.
}
};
idx_aware_wrapper operator[](std::size_t i) {
return idx_aware_wrapper(*this, i);
}
/* .... */
};
This allows quick access to any data in was_idx_aware, and the wrapper class can be augmented with all the methods that require interaction with the container. No need to store and keep indices up to date or override assignment operators.
How would I return a(n existing) pointer to a known type from a string of its name? Say I created some map<string, double> called map1 and some vector<string> called vec1. I'd like to write a function that will return map1 from "map1" and vec1 from "vec1" (and an additional argument specifying the respective type of each).
Is this possible?
My ultimate goal is to get a QWidget by its name in QString form, since I'm working with a large number of them, though an answer should be framework-independent, right?
You need to perform some kind of dynamic dispatch. To do so you can simply start with exactly what you proposed:
enum class types { A = 0, B = 1 };
void (*handlers[])(void*) = { &HandleA, &HandleB };
::std::unordered_map<::std::string, ::std::tuple<types, void*>> registry;
Now all that remains is to perform the lookup:
void lookup(::std::string const& name)
{
auto& t = registry.at(name);
handlers[static_cast<size_t>(::std::get<0>(t))](::std::get<1>(t));
}
Automagic argument casting for handlers
The handlers all take an argument of type void* - this can be dealt with by adding a little template magic:
template<typename T, void(*f)(T*)>
void handle(void* arg)
{
f(static_cast<T*>(arg));
}
void (*handlers[])(void*) = { &handle<A, &HandleA>, &handle<B, &HandleB> };
Now, the prototype is e.g. void HandleA(A*).
Simple adding of objects to registry
With the current code, you can add objects to your registry like so:
A a;
registry.emplace("A #1", ::std::make_tuple(types::A, &a));
While this works perfectly, we would like to do something a bit more elegant. Let us start by changing the enum class types to something which also knows about the type we whish to represent it:
template<typename T> struct types;
template<> struct types<A> { static const size_t id = 0; };
template<> struct types<B> { static const size_t id = 1; };
Of course, now we need to fix the registry type:
::std::unordered_map<::std::string, ::std::tuple<size_t, void*>> registry;
And finally we can provide a simple insert function:
template<typename T>
void insert(::std::string const& name, T* object)
{
registry.emplace(name, ::std::make_tuple(types<T>::id, static_cast<void*>(object)));
}
Final usage example
A a;
insert("A #1", &a);
lookup("A #1");
The meta-object system already handles this, so the answer will be framework-specific because you generally need a code generator to get metadata about the C++ types that's not otherwise available.
QLineEdit * ed = ...;
ed->setObjectName("myObject");
... elsewhere in the code
foreach(QWidget * w, QCoreApplication::allWidgets()) {
// Lookup by name
if (w->objectName() == "myObject") {
...
}
// Lookup by type
if (qobject_cast<QLineEdit*>(w)) {
...
}
}
If you want to speed up the lookup, and the objects have unique names:
class Widgets {
typedef QMap<QString, QPointer<QWidget>> Data;
mutable Data m_map;
public:
Widgets() {
foreach(QWidget * w, QCoreApplication::allWidgets()) {
if (w->objectName().isEmpty()) continue;
m_map.insert(w->objectName(), w);
}
}
QWidget * lookupWidget(const QString & name) const {
Data::iterator it = m_map.find(name);
if (it == m_map.end()) return nullptr;
QWidget * w = it->data();
if (!w) m_map.erase(it); // The widget doesn't exist anymore
return w;
}
template <typename T> T * lookup(const QString & name) const {
return qobject_cast<T*>(lookupWidget(name));
}
void setName(QWidget * w, const QString & name) {
Q_ASSERT(! name.isEmpty());
w->setObjectName(name);
m_map.insert(name, w);
}
};
In your code, use widgets->setName() instead of setObjectName.
If you want to look-up by both name and type, where duplicate names are OK as long as they are all of different types:
class Widgets2 {
typedef QPair<QString, QString> Key;
typedef QMap<Key, QPointer<QWidget>> Data;
mutable Data m_map;
static Key keyFor(QWidget * w) {
return qMakePair(w->objectName(),
QString::fromLatin1(w->metaObject()->className()));
public:
Widgets2() {
foreach(QWidget * w, QCoreApplication::allWidgets()) {
if (w->objectName().isEmpty()) continue;
m_map.insert(keyFor(w), w);
}
}
QWidget * lookupWidget(const QString & name, const QString & type) const {
Data::iterator it = m_map.find(qMakePair(name, type));
if (it == m_map.end()) return nullptr;
QWidget * w = it->data();
if (!w) m_map.erase(it); // The widget doesn't exist anymore
return w;
}
template <typename T> T * lookup(const QString & name) const
{
return qobject_cast<T*>(lookupWidget(name,
QString::fromLatin1(T::staticMetaObject.className())));
}
void setName(QWidget * w, const QString & name) {
Q_ASSERT(! name.isEmpty());
w->setObjectName(name);
m_map.insert(keyFor(w), w);
}
};
The lookup works as follows:
widgets2->lookup<QLineEdit>("myObject")->setText("foo");
I'm leveraging the QObject and QPointer to make the widget registry safe to widget deletions - you won't ever get a dangling pointer back.
It is also possible to track object name changes, if you so wish: QObject emits the objectNameChanged signal.
All of this is of course a horrible hack around a broken design of your code. The fact that you need this means that you're very tightly coupling business logic and the GUI. You should use some kind of model-view architecture.
I try to modify an existing object pool class so that I am able to pass an instance creator class as an argument to the object pool. Basically I want to be able to keep the actual object construction out of the memory pool so I have more freedom in what way I create instances to be pooled.
Here is the object pool definition:
template <
typename T,
typename InstanceCreator = DefaultInstanceFactory<T>
>
class ObjectPool : private noncopyable {
...
}
So I would create an ObjectPool like this
ObjectPool<int> intPool((DefaultInstanceFactory<int>()));
or
ObjectPool<IntClass, IntClass::InstanceFactory> intPool (IntClass::InstanceFactory (1));
The default Instance creator looks like this
template <typename T>
class DefaultInstanceFactory {
public:
T * operator ()() const {
return new T;
}
};
Inside that ObjectPool class is a nested class that stores the items
class PooledItem {
public:
char data[OBJECT_SIZE];
PooledItem * next;
bool initialized;
PooledItem()
: initialized(false) {}
~PooledItem() {
// --- call T destructor
if (initialized)
cast()->~T();
}
T * cast() {
return reinterpret_cast<T *>(data);
};
};
There is a borrowObject method to acquire an object and here is my actual problem:
T * borrowObject() {
PooledItem * item = getItem();
T * obj = item->cast();
if (! item->initialized) {
// old original line, call the defaut constructor of T
new (obj) T();
// how to integrate the external Instance Creator at this point?
//new (instCreator_ ()) T(1);
//instCreator_ ();
item->initialized = true;
}
if (obj == NULL) {
throw ObjectPoolException(
"Object is NULL!", __FILE__, __LINE__, __FUNCTION__);
}
return obj;
}
In above method I marked the actual problem lines. I have no idea how to replace the placement new new (obj) T() line with the external Instance creator, to just reuse that memory.
For completeness, the method for returning an object to the pool looks like this
void returnObject(T * obj) {
// --- Get containing PooledItem pointer
PooledItem * item = reinterpret_cast<PooledItem *>(obj);
// --- Make sure object came from this pool
if (item->next != reinterpret_cast<PooledItem *>(this)) {
// throw Exception
}
// --- Destroy object now if we want to reconstruct it later
if (destroyOnRelease) {
item->cast()->~T();
item->initialized = false;
}
Could anybody give me some help how to modify the methods so that the external Instance Creator gets integrated properly? I do not know up to now, if I need to change something in the returnObject method, up to now I think not.
Appreciate your help!
Sounds like you need to change InstanceFactory's signature to take a pointer
template <typename T>
class DefaultInstanceFactory {
public:
void operator ()(T* out) const {
return new(out) T;
}
};