I have a function cleanup()
void cleanup() {
// blah
}
int main() {
// many variable initializations
// call cleanup
cleanup(this); // <--- can i do this?
}
Can I pass main() into a function cleanup()?
And do the cleanup by doing things like:
this->something.close()
and
this->something = NULL
Thanks.
Re
โ Can I pass main() into a function cleanup()?
No, you cannot โ in a formally correct program โ because you are not allowed to take the address of main.
Instead of a named cleanup function you can simply use C++ destructors. Let each object clean up after itself, in its destructor. That's called RAII: Resource Acquisition Is Initialization (okay, it's a silly acronym).
No, you cannot do that. The this pointer is only available within the scope of a class, which you're not using. The main function is not defined within a class either.
Also, you cannot pass functions around in C++ because they're not 'first-class citizens'. You'd need to use function pointers to pass functions around, and even then, trying to pass main wouldn't make sense. This normally makes sense when a callback is needed, and main is certainly not up for that purpose.
I'd recommend you get started with an introductory tutorial to the C++ language, such as this one.
Related
Is it possible to adapt unique_ptr for plain c?
Perhaps if there is a way of simulating calls to a home made "constructor/destructor" when calling malloc/free?
Is it doable? Or is it just a silly idea?
The whole point of a "smart pointer" is to do certain tasks automatically on destruction. Since C doesn't have destructors there's no way to accomplish this except with explicit function calls - but that's how you deallocate memory in C already.
You could possibly make a list of pointers that need to be freed and do them all at the same time with a single function call.
No, not in plain C. You can do something similar with the cleanup GCC attribute (it is not standard):
#include <stdio.h>
void scope_leaving(int* p)
{
printf("Leaving scope.\n");
// this is essentially your "destructor"
}
int main(int argc, char* argv[])
{
printf("Before x is declared.\n");
{
int x __attribute__((cleanup (scope_leaving)));
x = 42;
}
printf("Scope was left.\n");
}
As you would expect, the output is this:
Before x is declared.
Leaving scope.
Scope was left.
With this, you can implement a pointer emulates the RAII semantics of unique_ptr, maybe using a macro for easier declaration. There is more to unique_ptr than that, but I'm not sure from your question if you want other aspects besides RAII.
On second reading, there's nothing that prevents your C structures from starting with a void(*)() pointer. If you have a custom_malloc(size_t size, void(*deleter)() which sets the pointer, your custom_free(void*) can subsequently call that deleter. This is similar to a virtual destructor from C++. However, the second part of std::unique_ptr is a delete'd copy constructor. You can't do that in C.
In order to implemented unique_ptr, you need two things:
assignment operator which transfers ownership;
destructor for when unique_ptr goes out-of-scope.
In order to implement (1), since C does not allow you to have function overloading, you need to "discipline" yourself and always call a custom assignment function or macro. C cannot force you to always have ownership transferred.
As for (2), GCC provides an extension: you are allow to assign a "cleanup" function, which is called once a variable gets out of scope. This can be used to implement a destructor for your unique_ptr.
In C++ what would be the best way to have an object that needs to be initalized in main(), but has to be global, so it can be accessed from other functions throughout the program? And make sure the destructor is called to make sure it gets cleaned up properly?
struct foo {};
foo *x_ptr;
int main() {
foo x;
x_ptr = &x;
// the rest
}
You can also use std::reference_wrapper if you don't want to access members via operator->.
But really, don't do that. Pass it along if it's needed, instead of making it global, e.g.
void needs_foo1(foo&);
void needs_foo2(foo&, int, int, int);
int main() {
foo x;
needs_foo1(x);
needs_foo2(x, 1, 2, 3);
// et cetera
}
I suspect that "global" is a solution rather than a requirement. As it has been suggested you could always pass your object around explicitly.
If you don't want to do that I'd probably use a shared::ptr, possibly wrapped in a Singleton implementation. Your shared_ptr would be initialized to null at program start-up and set to a valid value in main().
Beware that you may encounter order of destruction problems if you have global variables that depend on other global variables. There's also a huge literature about the drawbacks of the Singleton patterns.
I want to use unique_ptr in a method. I want to rely on the fact that it is destroyed at the closing brace of the method (if that is indeed true).
The reason why I want to rely on this fact is that I want to write a simple class for logging that says when it has entered/exited a method, something like:
class MethodTracing
{
string _signature;
public:
MethodTracing(string signature)
{
_signature=signature;
BOOST_LOG_TRIVIAL(trace) << "ENTERED " << _signature ;
}
~MethodTracing()
{
BOOST_LOG_TRIVIAL(trace) << "EXITED " << _signature;
}
};
I can then use it like so:
void myMethod( )
{
auto _ = unique_ptr<MethodTracing>(new MethodTracing(__FUNCSIG__) ) ;
/// ...
}
Is it true (and consistent) that a unique_ptr, when created in a method, is destroyed at the end of the method (assuming it's not passed around).
Are there any other hidden (or otherwise!) pitfalls that I should be aware of?
Update:
As most of the answers suggested, I could have used local variable scoping. I tried this with MethodTracing(__FUNCSIG__);, but of course, I didn't assign a local variable! so it immediately went out of scope. I thought the runtime was being clever, but no, it was me being stupid (too long in C#!)
You don't need to do that - rely on automatic storage, e.g.
void myMethod( )
{
MethodTracing __sig(__FUNCSIG__);
// do stuff
}
__sig will be destroyed at the end of the function scope automatically
(yes __sig is bad form, call it something else if you want)
Yes, unique_ptr is destroyed at the end of the scope it's created in. However you don't need unique_ptr to get this functionality, because all C++ classes have this. You might as well just create your MethodTracing object directly:
void myMethod( )
{
MethodTracing _(__FUNCSIG__);
/// ...
}
You can usually rely on it. The exception would be code that explicitly calls terminate(). In general, destructors of objects are called when they go out of scope (for local variables, that is the end of the method). This is the foundation of RAII.
Yes that is true. But it is not necessarily when control flows through the closing brace. It can be because of a return, an exception or a goto out of its block.
However care should be taken when calling exit() to terminate the program. The local automatics like your unique ptr will no be destroyed then.
You ought to ensure that your ~MethodTracing destructor is no-throw if it is more complex that what you describe above, otherwise your class might only be partially destroyed.
Personally, I'd just declare it on the stack as mentioned above.
This is probably a philosophical question, but I ran into the following problem:
If you define an std::function, and you don't initialize it correctly, your application will crash, like this:
typedef std::function<void(void)> MyFunctionType;
MyFunctionType myFunction;
myFunction();
If the function is passed as an argument, like this:
void DoSomething (MyFunctionType myFunction)
{
myFunction();
}
Then, of course, it also crashes. This means that I am forced to add checking code like this:
void DoSomething (MyFunctionType myFunction)
{
if (!myFunction) return;
myFunction();
}
Requiring these checks gives me a flash-back to the old C days, where you also had to check all pointer arguments explicitly:
void DoSomething (Car *car, Person *person)
{
if (!car) return; // In real applications, this would be an assert of course
if (!person) return; // In real applications, this would be an assert of course
...
}
Luckily, we can use references in C++, which prevents me from writing these checks (assuming that the caller didn't pass the contents of a nullptr to the function:
void DoSomething (Car &car, Person &person)
{
// I can assume that car and person are valid
}
So, why do std::function instances have a default constructor? Without default constructor you wouldn't have to add checks, just like for other, normal arguments of a function.
And in those 'rare' cases where you want to pass an 'optional' std::function, you can still pass a pointer to it (or use boost::optional).
True, but this is also true for other types. E.g. if I want my class to have an optional Person, then I make my data member a Person-pointer. Why not do the same for std::functions? What is so special about std::function that it can have an 'invalid' state?
It does not have an "invalid" state. It is no more invalid than this:
std::vector<int> aVector;
aVector[0] = 5;
What you have is an empty function, just like aVector is an empty vector. The object is in a very well-defined state: the state of not having data.
Now, let's consider your "pointer to function" suggestion:
void CallbackRegistrar(..., std::function<void()> *pFunc);
How do you have to call that? Well, here's one thing you cannot do:
void CallbackFunc();
CallbackRegistrar(..., CallbackFunc);
That's not allowed because CallbackFunc is a function, while the parameter type is a std::function<void()>*. Those two are not convertible, so the compiler will complain. So in order to do the call, you have to do this:
void CallbackFunc();
CallbackRegistrar(..., new std::function<void()>(CallbackFunc));
You have just introduced new into the picture. You have allocated a resource; who is going to be responsible for it? CallbackRegistrar? Obviously, you might want to use some kind of smart pointer, so you clutter the interface even more with:
void CallbackRegistrar(..., std::shared_ptr<std::function<void()>> pFunc);
That's a lot of API annoyance and cruft, just to pass a function around. The simplest way to avoid this is to allow std::function to be empty. Just like we allow std::vector to be empty. Just like we allow std::string to be empty. Just like we allow std::shared_ptr to be empty. And so on.
To put it simply: std::function contains a function. It is a holder for a callable type. Therefore, there is the possibility that it contains no callable type.
Actually, your application should not crash.
ยง 20.8.11.1 Class bad_function_call [func.wrap.badcall]
1/ An exception of type bad_function_call is thrown by function::operator() (20.8.11.2.4) when the function wrapper object has no target.
The behavior is perfectly specified.
One of the most common use cases for std::function is to register callbacks, to be called when certain conditions are met. Allowing for uninitialized instances makes it possible to register callbacks only when needed, otherwise you would be forced to always pass at least some sort of no-op function.
The answer is probably historical: std::function is meant as a replacement for function pointers, and function pointers had the capability to be NULL. So, when you want to offer easy compatibility to function pointers, you need to offer an invalid state.
The identifiable invalid state is not really necessary since, as you mentioned, boost::optional does that job just fine. So I'd say that std::function's are just there for the sake of history.
There are cases where you cannot initialize everything at construction (for example, when a parameter depends on the effect on another construction that in turn depends on the effect on the first ...).
In this cases, you have necessarily to break the loop, admitting an identifiable invalid state to be corrected later.
So you construct the first as "null", construct the second element, and reassign the first.
You can, actually, avoid checks, if -where a function is used- you grant that inside the constructor of the object that embeds it, you will always return after a valid reassignment.
In the same way that you can add a nullstate to a functor type that doesn't have one, you can wrap a functor with a class that does not admit a nullstate. The former requires adding state, the latter does not require new state (only a restriction). Thus, while i don't know the rationale of the std::function design, it supports the most lean & mean usage, no matter what you want.
Cheers & hth.,
You just use std::function for callbacks, you can use a simple template helper function that forwards its arguments to the handler if it is not empty:
template <typename Callback, typename... Ts>
void SendNotification(const Callback & callback, Ts&&... vs)
{
if (callback)
{
callback(std::forward<Ts>(vs)...);
}
}
And use it in the following way:
std::function<void(int, double>> myHandler;
...
SendNotification(myHandler, 42, 3.15);
I am working on a c++ application.
In my code i have an object pointer like
TestClass *pObj = new TestClass();
and Member function call like pObj->close();
Inside close() member function, i should make pObj to NULL.
As per our requirement, TestClass users should not call delete on pObj.(Destructor of TestClass is made private intentionally for this purpose)
Also, TestClass should not expose any static method to receive a pointer and making it NULL.
Is there any other way to make pObj to NULL once close() is called ?
I tried one way.
Inside close() function, i removed constness for this pointer using const_cast.
and took a reference of it.
Then i made this = NULL.
Even then calling side, pObj pointer value remains. It is not getting set to NULL.
It may be due to the Address of this pointer and Address of pObj are different.
Pls help.
EDIT: Sorry, i missed something. new is getting called inside a static function called init. init function is like below. void init(TestClass *& pObj); So TestClass user calls init first for allocation. But he can't call deinit(there should not be any such function) Actually, this is not my design. It was present when i entered this project :(
Imagine such code:
TestClass *ptr1 = new TestClass();
TestClass *ptr2 = ptr1;
ptr2->close();
Which pointer do you want to be set to null? Inside close method you have no information how many pointers point to your object and how is close method accessed.
There's no way of doing what you want, given your constraints.
One warning: what happens if the user of your class creates on object on the stack: TestClass test;?
One question more, why do you want the users of your class being forced to call new to allocate objects of your class, but then being forbid to call delete. Makes no sense to me.
An insane problem requires an insane solution, so here is one. You can't do exactly what you want, since it's impossible to keep track of the raw pointers to your object. However, if you use some kind of smart pointer, then they can be tracked and nullified when the object is destroyed. This is a common requirement in less insane circumstances, so there are already smart pointers to do this: shared_ptr to keep the object alive, and weak_ptr to track the object and go null when it's destroyed. So the solution would look something like this:
class TestClass
{
public:
static weak_ptr<TestClass> create()
{
shared_ptr<TestClass> shared(new TestClass);
shared->self = shared;
return shared;
}
void close()
{
self.reset();
}
private:
shared_ptr<TestClass> self;
};
int main()
{
weak_ptr<TestClass> object = TestClass::create();
weak_ptr<TestClass> copy = object;
assert(!object.expired());
assert(!copy.expired());
object.lock()->close();
assert(object.expired());
assert(copy.expired());
}
As per our requirement, TestClass users should not call delete on pObj.(Destructor of TestClass is made private intentionally for this purpose) Also, TestClass should not expose any static method to receive a pointer and making it NULL.
Who set those requirements? For each of them, ask "Why?". They seem absolutely arbitrary, they make no sense.
and Member function call like pObj->close(); Inside close() member function, i should make pObj to NULL.
Again, "Why?". Disregarding changing this from inside of a function is not possible, using such style is crazy. A normal C++ way is to destruct the object instead.
If you will get no reasonable answer to your "whys", you should probably consider quitting the job, or prepare to spend your time there in frustration. The design "requirements" you have presented are really extraordinary crazy.
No. Consider the following code:
TestClass * const pObj = new TestClass();
pObj->close();
The compiler will not reject the code, even if close would be const. The pointer is const, but not the new TestClass object. Therefore you can call non-const methods via the pointer, but you can't change the pointer itself. That means you can't set it to NULL either.
It basically means that you need to set this pointer to NULL. This is not possible as far as I know. If it helps you can think the calling of the method taking this pointer by value i.e. whatever change you do inside the method will not be reflected outside.
while you're writing terrible code you may as well add some inline assembly and xor ecx,ecx just before you return from close().
Probably won't work unless you happen to be super careful with the pObj init returns to not to anything fancy with it.
#include <map>
std::map<TestClass*, TestClass**> pointers();
void init(TestClass *& pObj)
{
pObj = new TestClass();
pointers[pObj] = &pObj;
}
void TestClass::Close()
{
*pointers[this] = null;
pointers.erase(this);
delete this;
}
Though, it is full of dangers, a way could be
TestClass::Close(Testclass *&p){
p = NULL;
}
pObj->close(pObj);
EDIT: After explanation on restriction of Close();
Is pObj accessible in scope of 'TestClass::Close'? e.g. a namespace scope variable?
If yes, the TestClass::Close method can simply set pObj = NULL;
If no, there is no way IMHO