Boost::bind documentation states:
By default, bind makes a copy of the provided function object. boost::ref and boost::cref can be used to make it store a reference to the function object, rather than a copy.
I am seeing excessive news and deletes in my code when I use boost::bind with a pointer to a member function. The documentation is unclear to me whether boost::bind(&classname::functionname,...) makes a copy of the function.
Or maybe the question makes no sense and as it is converting a member function into a function object it obviously has to new the function object.
So my question is there a way I can bind to a member function and avoid the new and delete?
According to my experiments (boost 1.49), boost::bind does not use dynamic memory for its own implementation. With this code
#include <boost/bind.hpp>
int f(int a , int b) {
return a>b ? a+b : a-b;
}
int main()
{
auto a = boost::bind(f, _1, 2);
return a(0);
}
I tried breaking on operator new variants in gdb and it didn't fire. So I suspect your problem is actually that boost::bind is making copies of either the bound arguments (compare the output of these two snippets) or the call arguments. Search for something among these that could allocate memory while copying, and try to get rid of it.
If you're using a C++11 compiler, you can get away with boost::bind completely and use a lambda function instead. The example would be transformed to
auto a = [&](int a1) { return f(a1, 2); }
That would only copy if you'd capture objects by value.
EDIT: With the code you posted, try changing the line in question to
TConstIterator pIt = std::find_if(rtContainer.begin(), rtContainer.end(),
boost::bind(&TValueType::bSameSocket, boost::cref(rtData), _1));
^^^^^^^^^^^
That should make it better; report if it doesn't.
What gets copied is the pointer to that method, so no new/delete involved. What bind returns is a function object that gets created and destroyed at some point, but again no dynamic memory allocation.
As far as I can tell if you use boost::bind in code such as to create a function object to act as the predicate in a find_if the function object is newed and deleted and this is what was causing my code to run slowly.
My question was: is there a way I can bind to a member function and avoid the new and delete?
I worked around the boost::bind by iterating through the list myself calling a member function through a member function pointer.
The type of the member pointer function is derived from template parameters for the list and its stored data types, but the same technique works whether the types are templated or not.
This solution reduced the user perception of response for a particular action from 5 minutes to effectively immediately.
Related
Every time I write a signature that accepts a templated callable, I always wonder what the best type for the parameter is. Should it be a value type or a const reference type?
For example,
template <class Func>
void execute_func(Func func) {
/* ... */
}
// vs.
template <class Func>
void execute_func(const Func& func) {
/* ... */
}
Is there any situation where the callable is greater than 64bits (aka a pointer to func)? Maybe std::function behaves differently?
In general, I do not like passing callable objects by const reference, because it is not that flexible (e.g. it cannot be used on mutable lambdas). I suggest to pass them by value. If you check the stl algorithms implementation, (e.g. for std::for_each), all of the callable objects are passed by value as well.
Doing this, the users are still able to use std::ref(func) or std::cref(func) to avoid unnecessary copying of the callable object (using reference_wrapper), if desired.
Is there any situation where the callable is greater than 64bits
From my experience in working in CAD/CAE applications, a lot. Functors can easily hold data that is bigger than 64 bits. More than two ints, more than one double, more than one pointer, is all you need to exceed that limit in Visual Studio.
There is no best type. What if you have noncopyable functor? First template will not work as it will try to use deleted copy constructor. You have to move it but then you will loose (probably) ownership of the object. It all depends on intended use. And yes, std::function can be much bigger than size_t. If you bind member function, it already is 2 words (object pointer and function pointer). If you bind some arguments it may grow further. The same goes with lambda, every captured value is stored in lambda which is basically a functor in this case. Const reference will not work if your callable has non const operator. Neither of them will be perfect for all uses. Sometimes the best option is to provide a few different versions so you can handle all cases, SFINAE is your friend here.
I currently have a memory leak in my project. To resolve the memory leak, I am trying to replace the pointers into std:: unique_ptr. The pointer to the heap is not from my project, but rather from a library called Xerces(an XML parsing library).
In this library, it can transcodes char * to XMLCh * in both ways.
So in real code, it comes like ..
XMLCh * xmlstr = XMLString::transcode("abc",...);
char * charstr = XMLString::transcode(xmlstr,...);
since both methods allocates heap area and returns the pointer for it, I should explicitly call
XMLString::release(xmlstr);
XMLString::release(charstr);
after using it to clean up. I want to write a custom deleter for two types (char * and XMLCh *) using std::unique_ptr.
The release method has a type of
XMLString::release(char **str);
XMLString::release(XMLCh **str);
It is using double pointer because it sets the pointer to null after release.
I thought to make the template accept reference pointers like this,
template<typename T>
void release(T *& ptr){
XMLString::release(ptr);
}
but just realized that it will be possible to
XMLCh * xmlstr = XMLString::transcode("abc",...);
auto uptr = unique_ptr<XMLCH, decltype(&release<T>)>(xmlstr)
do this, but not possible to
auto xmluptr = unique_ptr<XMLCH, decltype(&release<T>)>(XMLString::transcode("abc",...));
do something like this, because it is accepting a rvalue in the parameter but the argument is a reference pointer. Is it possible to instantiate both cases writing only one template function?
By the way, I am using c++11.
So if I understand correctly, your problem is that XMLString::release takes a pointer-to-point and it does not fit into the unique_ptr release function. Well, the correct solution is to wrap it like
template<typename T>
void release(T *ptr){
XMLString::release(&ptr);
}
The XMLString::release will only null-out the copy of the pointer inside the wrapper, but since the unique_ptr takes care of rendering itself unusable itself, you don't need that functionality of XMLString::release.
In either case, the type of the release wrapper does not affect how the unique_ptr is constructed, because the release wrapper will be called with the internal member of the unique_ptr as argument. So either unique_ptr accepts that argument, and both assignments will work, or unique_ptr won't accept it and neither will.
That said, the point of unique_ptr is that you wrap the pointer in it immediately when you get it. So don't store it in variable before.
I have the following lambda
direction->addClickEventListener([=](Ref* sender){
std::unordered_map<int,int> data;
rep->getData(DIRECTION, data);
int last = data[1];
int rotation = (last + 45)%360;
LOG("l:%i r:%i",last,rotation);//Always logs l:0 r:45
direction->setRotation(rotation);
data[1] = rotation;
rep->setData(DIRECTION, data);
});
where getData is:
void getData(DATA_KEY key,std::unordered_map<int,int>& data){
//Modifies data with the appropriate values for key, for the current state of rep
}
void setData(DATA_KEY key,std::unordered_map<int,int>& data){
//Makes a copy of data stores it internally with key
}
rep is pointer, so I thought that whenever the lambda is called, the current value of data will always reflect the current state of rep. But it seems that it is always the value of whatever rep was at the time direction->addClickEventListener was called.
If I want to use the current state of rep, how ghouls I modify my lambda ?
EDIT: Since rep is a pointer, I can't can't capture by reference..
I'm not really sure what you're asking, so this might not be an answer to your problem, but it is an attempt to clarify what the problem with capturing by reference is.
It looks like you are having an event-based system. The important thing to know about events is that they can occur at any time.
Now lets say you have something like this (very simplified and pseudo-ish):
void some_function(some_type* rep)
{
add_event_listener([&]()
{
do_something(rep);
});
}
There is a very serious bug in the code above: When the event is invoked and the lambda is called, the function some_function will have returned, and therefore the scope of the local variable rep doesn't exist any more. So when rep is used in the lambda it is a reference to a variable that doesn't exist anymore (remember that rep is a local variable). That of course leads to undefined behavior.
If you capture by value instead, the pointer is copied meaning you now have two pointer variables, both pointing to the same memory. Then it doesn't matter if the first variable goes out of scope, because the second variable still is valid.
Pointer doesn't have state, methods or something. Pointer is abstract address of storage where your object is. "Reference" is synonymous to pointer in some ways, if you think in C terms, but they are different in C++ - you can pass pointer variable by reference, thus passing control over its value (not over the state of object it points to, that actually achieved by pointer). Pointer variable is also a storage, that contains value of pointer
You can pass any variable (storage) "by reference", which means that function can change value stored in that variable. In C that was done by passing pointers, but to pass pointer "by reference" they had to pass type like void** pointer to a pointer. In C++ & syntax is used to reduce the clutter.
[=] mans that all external variables are captured by value. This would allow anonymous function to read value of pointer, deference it and call methods\access fields of the objects it points to.
[&] would mean capture by reference. Pointer is variable. This would allow lamba to modify it, making it to point to other object.
If you do need only rep by reference use, [=. &rep].
How rep might be changed while lambda is running? If that happens in parallel thread, you'll probably need an atomic.
If you cannot change actual object your pointer refers to, that may mean that compiler does aliasing optimization because of illegal cast from one object to another, because casted away const modifier or low quality of implementation (that's rare) that causes aliasing optimization where it should not happen.
I have a class exposing through it's interface add function:
void AddObject(Object *o);
Inside the class I maintain the objects in set<shared_ptr<Object>>.
Since I will create shared_ptr from the received pointer I thought to limit the function argument to only rvalue pointers so to make sure that the user will not delete the pointer I use. And so I'll change the function declaration to:
void AddObject(Object* &&o);
so a typical use will be:
AddObject(new Object())
preventing the user to accidentally delete pointer I hold.
I don't want to to use shared_ptr in the interface because the user is not familiar with shared_ptr.
Do you think my suggestion is a good idea?
I think this is a bad idea. I'm sure there is a reason why shared_ptr c-tor that gets a raw pointer is marked explicit instead of using r-value. In my eyes, It's better to teach the users once about smart pointers or at least teach them about using make_shared/make_unique (which are safer and, in the case of make_shared, more efficient, BTW).
BTW, why shared_ptr and not unique_ptr?
Also, why set? Even if you want to make sure you hold each pointer only once and searching a vector each time doesn't look natural enough in your code, I don't see a reason to hold the pointers sorted instead of using unordered_set.
First of all, this approach will not prevent the user from deleting the pointer. Consider this example
auto obj = new Object();
AddObject(std::move(obj));
delete obj;
Secondly, the amount of steps between calling new and the creation of shared_ptr should be as few as possible. If anything happens inside AddObject before it can create a shared_ptr, the object will never get deleted.
The same applies if there are more arguments to AddObject(). If constructing those fails, you will leak memory.
void AddObject(Object* &&o, SomeOtherObject* x);
AddObject(new Object(), xx()); // if xx() throws, memory leak will occur
Ideally you would "wrap" object creating into shared_ptr construction:
void AddObject(std::shared_ptr<Object> o);
AddObject(std::make_shared<Object>());
Either of the following methods may solve your problem.
You may append more comments for AddObject to tell users that delete the pointer they added is not allowed. This is almost enough.
Or, you could also make Object inherits from a base class which has a private destructor and a method named destroyByOwner.
Is it legal/proper c++0x to leave an object moved for the purpose of move-construction in a state that can only be destroyed? For instance:
class move_constructible {...};
int main()
{
move_constructible x;
move_constructible y(std::move(x));
// From now on, x can only be destroyed. Any other method will result
// in a fatal error.
}
For the record, I'm trying to wrap in a c++ class a c struct with a pointer member which is always supposed to be pointing to some allocated memory area. All the c library API relies on this assumption. But this requirement prevents to write a truly cheap move constructor, since in order for x to remain a valid object after the move it will need its own allocated memory area. I've written the destructor in such a way that it will first check for NULL pointer before calling the corresponding cleanup function from the c API, so that at least the struct can be safely destroyed after the move.
Yes, the language allows this. In fact it was one of the purposes of move semantics. It is however your responsibility to ensure that no other methods get called and/or provide proper diagnostics. Note, usually you can also use at least the assignment operator to "revive" your variable, such as in the classical example of swapping two values.
See also this question