I know Java but don't have much knowledge of C++. I am trying to write a class for the first 3 statements in main function of the code at https://developers.google.com/v8/get_started.
First I have questions about how objects are created in C++. See the below code.
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
I think in C++ when you declare a variable of a class an instance of the class created at the point. You do not need to use new keyword like in Java. So the first statement would create an instance of HandleScope which will be stored in handle_scope.
Now I do not understand how the second statement would work. With my knowledge the part before = will create a new Persistent object which can be referred by the variable context. Then Context::New() will create a new object and store it in context? Huh, I know I am wrong. But I simply dont get how it would work?
I am trying to write a C++ class for the above. Here is my attempt.
class MyClass {
private:
HandleScope handle_scope;
Persistent<Context> context;
Context::Scope context_scope;
public:
MyClass();
};
MyClass::MyClass()
{
context = Context::New();
context_scope = new Context::Scope(context);
}
Have I done the initialization properly?
EDIT: Reply to peachykeen (in comments)
I did the following experimentation.
I wrote a Test class as below.
Test
{
public:
Test() {
cout << "Test" << endl;
}
};
In the main function I wrote Test test; It outputs "Test" which means an object is created without using new keyword.
You are right, in C++, objects are created as soon as they're defined. You do not need to use the new keyword.
However, unlike in Java, objects can be created with different kinds of duration. Using new creates an object on the heap, with dynamic storage duration: the variable lives until you explicitly delete it. (And new returns a pointer to the created object, so that you can track it)
If you simply define an object, as in your first and third lines, then it is created with automatic storage duration: that is, the object exists until it goes out of scope.
This means that you can create objects inside a function, and be guaranteed that they'll be destroyed as soon as you leave the function -- regardless of how you leave the function. Whether you return, or throw an exception, all objects with automatic storage duration (created without using new) are guaranteed to be properly cleaned up.
This means that you should always avoid new whenever possible. If you have to use new, you should typically wrap the resulting pointer into a smart pointer class, an object created with automatic storage duration, so that it gets destroyed automatically). The smart pointer will then call delete on the new-allocated object automatically, ensuring, again, that you don't leak memory.
This distinction is a very powerful tool, which good C++ programmers need to understand well. It is a key to avoiding memory leaks, or more generally, resource leaks of all kinds, and it is, in some respects, more powerful than Java's garbage collector.
For example, say we wish to open a file, and then write some data to it. In C++, we can do it like this:
void foo() {
std::ofstream file("foo.txt");
doStuff(file); // call a function which does something with the file
}
And because file was declared without using new, because it has automatic storage duration, we are guaranteed that it will have its destructor invoked when it goes out of scope, and it will be properly cleaned up -- that is, the stream will be flushed, and the file handle will be closed.
It doesn't matter if doStuff might throw an exception. No matter how we leave foo, file will be properly destroyed, so we don't need to mess about with try/finally like you would in Java. The class is exception-safe by itself, without requiring any additional effort from the user.
Try writing a similar snippet in Java, one which guarantees that even if doStuff throws an exception, the file will be immediately closed. It'll be much longer, and requires more care on the part of the user.
Persistent<Context> context = Context::New();
create object of type Persistent<Context>, initialized from returned of Context::New, if c-tor is not explicit.
Simple example.
#include <iostream>
class C
{
public:
C(int)
{
std::cout << "C::C(int)" << std::endl;
}
};
int main()
{
C c = 1;
}
your class should be
class MyClass {
private:
HandleScope handle_scope;
Persistent<Context> context;
Context::Scope context_scope;
public:
MyClass();
};
MyClass::MyClass():context(Context::New()),
context_scope(Context::Scope(context))
{
}
if Context::Scope is not pointer.
This would be the equivalent class:
class MyClass {
private:
HandleScope handle_scope;
Persistent<Context> context;
Context::Scope context_scope;
public:
MyClass();
};
MyClass::MyClass()
: context(Context::New()),
context_scope(context)
{
}
When you write a statement like this:
Persistent<Context> context = Context::New();
You are constructing context using the copy constructor. This is different from creating the object and then assigning a new value, although the result might often be equivalent.
Likewise this statement:
Context::Scope context_scope(context);
is constructing context_scope and passing context to the constructor. You get the equivalent behavior in a class using the constructor initializer syntax as in my example.
To create an instance of an object, you need only this: Type name; The newkeyword creates a pointer to an object. Normally, to initialize the object, we use parenthesis: Type name(parameter); Sometimes, when an object supports copying, you can use a function that returns an object and assign it to that object: Type name = Some_function_that_returns_Type(); You can now use name like any other object. If you say Type name = new Type;, you will get a compiler error. The keyword new returns a pointer. It would be correct to say Type * name = new Type;. (Note the *, saying that it is a pointer to a Type class, named name. When I refer to Type it is any object, such as your HandleScope. When I refer to name, it is the new object you are creating. The all of all is this: new is a completely different keyword that refers to pointers. If you are not using pointers, don't use it. Use the basic format Type name(parameter, another_param);.
Related
I have passed as callback a C++ member function to a C# project through a C++/CLI wrapper (this works fine). The C# project is going to call this delegate when receiving data from another .exe process: an event will be raised and a method will call this callback. So, I needed to "save" this Action delegate using an static instance of a C# class already created. I got the following code:
// C++ unmanaged function
WRAPPER_API void dispatchEvent(std::function<void(int)> processEvent)
{
Iface::Wrapper wrapper;
wrapper.callback = &processEvent;
wrapper.PassCallback();
}
//C++ Managed
public ref class Wrapper
{
public:
std::function<void(int)>* callback;
void ReturnToCallback(int data)
{
(*callback)(data);
}
void PassCallback()
{
StartGenerator^ startGen = gcnew StartGenerator(gcnew Action<int>(this, &Wrapper::ReturnToCallback));
}
};
// C#
public class StartGenerator
{
private Communication comm;
public StartGenerator(Action<int> callback)
{
comm = Communication.Instance;
comm.callback = callback;
}
}
If I call the Action delegate in StartGenerator method, the C++ function is properly executed. However, my goal was saving the delegate to be able to call it afterwards, when data is received from another .exe process. When this data arrives, an event is raised and callback is called from the event method. It is at this point when I get the following exception:
Unhandled Exception: System.AccessViolationException: Attempted to
read or write protected memory. This is often an indication that other
memory is corrupt. at
Iface.Wrapper.ReturnToCallback(Int32 data)
I think I need to manage the lifetime of the std::function, I don't know about the lifetime of the function object being pointed to by the managed class. The object seems to be deleted and the managed class is left holding a dangling pointer.
I think I need to manage the lifetime of the std::function
Yes, I told you as much when I told you to store a pointer in the managed wrapper, here
I don't know about the lifetime of the function object being pointed to by the managed class.
The std::function is a native object and follows the native C++ rules. Putting a pointer in a managed wrapper won't make it garbage-collected.
The object seems to be deleted and the managed class is left holding a dangling pointer.
Yes, your terminology isn't exact but you've correctly diagnosed the problem. Take a look:
void dispatchEvent(std::function<void(int)> processEvent)
{
Iface::Wrapper wrapper;
wrapper.callback = &processEvent;
wrapper.PassCallback();
}
processEvent is function argument, a std::function object passed by value. The copy made and stored in the argument lives until the end of scope. It has automatic storage duration. When the function returns, all the local variables, function arguments included, are destroyed (not "deleted").
You will need to dynamically allocate (a copy of) the std::function object, like:
typedef std::function<void(int)> cbfn;
wrapper.callback = new cbfn(processEvent);
Now you have a memory leak, but at least you aren't using the object after it's destroyed. If you only make a handful of these objects the leak might even be acceptable. In general, you should implement IDisposable on your wrapper and have the Dispose method do delete callback;. In C++/CLI you use destructor syntax to accomplish that.
~Wrapper()
{
delete callback;
callback = nullptr;
}
look at my code:
#include <iostream>
using namespace std;
class MyClass{
public:
char ch[50] = "abcd1234";
};
MyClass myFunction(){
MyClass myClass;
return myClass;
}
int main()
{
cout<<myFunction().ch;
return 0;
}
i can't understand where my return value is stored? is it stored in stack? in heap? and does it remain in memory until my program finished?
if it be stored in stack can i be sure that my class values never change?
please explain the mechanism of these return. and if returning structure is different to returning class?
MyClass myClass; is stored on the stack. It's destroyed immediately after myFunction() exits.
When you return it, a copy is made on the stack. This copy exists until the end of the enclosing expression: cout << myFunction().ch;
Note that if your compiler is smart enough, the second object shouldn't be created at all. Rather, the first object will live until the end of the enclosing expression. This is called NRVO, named return value optimization.
Also note that the standard doesn't define "stack". But any common implementation will use a stack in this case.
if returning structure is different to returning class?
There are no structures in C++; keyword struct creates classes. The only difference between class and struct is the default member access, so the answer is "no".
It's up to the implementation to find a sensible place to store that value. While it's usually on the stack, the language definition does not impose any requirements on where it's actually stored. The returned value is a temporary object, and it gets destroyed at the end of the full statement where it is created; that is, it gets destroyed at the ; at the end of the line that calls myFunction().
When you create an object in any function it's destroyed as soon as the function execution is finished just like in variables.
But when you return a object from a function firstly compiler creates a local instance of this object in heap called unnamed_temporary then destroyes the object you created. And copies the contents of unnamed_temporary on call. Then it destroyes this unnamed _temporary also.
Anything you create without the keyword new will be created in stack.
Yes,contets of your variable ch will not change unless you access that variable and change it yourself.
The instance returned by myFunction is temporary, it disappears when it stop to be useful, so it doesn't exist after after the cout <<.... Just add a destructor and you will see when it is called.
What do you mean about can i be sure that my class values never change? ? You get a copy of the instance.
returning structure is different to returning class? : a struct is like a class where all is public by default, this is the alone difference.
Your function is returning a copy of an object. It will be stored in the stack in memory.
The returning obj. will exist until the scope of that function. After that, it will be destroyed. Then, your expression cout<<function(); will also have the copy of that obj. which is returned by the function. IT will be completely destroyed after the running of this cout<<function(); expression.
Is it possible to avoid the GC for delegates?
I am building a task system. I have N-Threads with a local task queue. A task queue is basically just a Array!Fiber tasks. Because it is discouraged to send fibers to a different thread, I am sending a closure/delegate to a thread, create the fiber from that delegate and put it in the array tasks.
Now the delegates that I am sending are delegates that capture variables.
//Some Pseudo code
auto f = //some function;
auto cell = Cell(...);
auto del = () {
let res = f();
cell.write(res);
}
send(del);
}
Now cell is heap allocated and synchronized with an atomic counter. I can then check if the atomic counter from cell has reached 0, if it did I can safely read from it.
The problem is that delegates which capture variables, allocate the variables on the GC. Now I only allocate a pointer and it is probably not a huge problem but I would still like to avoid the GC.
How would I do this?
You might already know all this, but this is a bit of a FAQ so I'm going to write a few details.
First, let's understand what a delegate is. Like how a slice is just a C data pointer paired with a length, a delegate is just a C data pointer paired with a function pointer. These are passed together to functions expecting them, as if it was defined
struct d_delegate {
void* ptr; // yes, it is actually typed void*!
T* funcptr; // this is actually a function pointer
};
(Note that the fact that there is just one data ptr in there is the reason behind some compiler errors when you try to take a nested delegate inside a class method!)
That void* is what points to the data and like with a slice, it can come from a variety of places:
Object obj = new Object();
string delegate() dg = &obj.toString;
At this point, dg.ptr points to obj, which happens to be a garbage collected class object, but only because I newed it above.
struct MyStruct {
string doSomething() { return "hi"; }
}
MyStruct obj;
string delegate() dg = &obj.doSomething;
In this case, obj lives on the stack due to how I allocated it above, so the dg.ptr also points to that temporary object.
Whether something is a delegate or not says nothing about the memory allocation scheme used for it - this is arguably dangerous because a passed delegate to you might point to a temporary object that will disappear before you're finished with it! (That's the main reason why GC is used by the way, to help prevent such use-after-free bugs.)
So, if delegates can come from any object, why are they assumed to be GC so much? Well, the automatically generated closure can copy local variables to a GC segment when the compiler thinks the lifetime of the delegate is longer than the outer function.
void some_function(void delegate() dg);
void foo() {
int a;
void nested() {
a++;
}
some_function(&nested);
}
Here, the compiler will copy the variable a to a GC segment because it assumes some_function will keep a copy of it and wants to prevent use-after-free bugs (which are a pain to debug as it frequently leads to memory corruption!) as well as memory leaks.
However, if you promise the compiler that you'll do it right yourself by using the scope keyword on the delegate definition, it will trust you and leave the locals right where they are:
void some_function(scope void delegate() dg);
Keeping the rest the same, it will no longer allocate a copy. Doing it on the function definition side is the best because then you, as the function author, can ensure you don't actually keep a copy.
On the usage side though, you can also label it scope:
void foo() {
int a;
void nested() {
a++;
}
// this shouldn't allocate either
scope void delegate() dg = &nested;
some_function(&dg);
}
So, the only time memory is automatically allocated by the GC is when local variables are used by a nested function which has its address taken without the scope keyword.
Note that the () => whatever and () { return foo; } syntaxes are just shorthand for a named nested function with its address being automatically taken, so they work the same way as the above. dg = {a++;}; is the same as dg = &nested; above.
Thus, the key takeaway from this for you is that if you want to manually allocate a delegate, you just need to manually allocate an object and make a delegate from one of its methods instead of automatically capturing variables! But, you need to keep track of the lifetime and free it properly. That's the tricky part.
So for your example:
auto del = () {
let res = f();
cell.write(res);
};
you might translate that into:
struct Helper {
T res;
void del() {
cell.write(res);
}
}
Helper* helper = malloc(Helper.sizeof);
helper.res = res; // copy the local explicitly
send(&helper.del);
Then, on the receiving side, don't forget to free(dg.ptr); when you're done so you don't leak it.
Or, better yet, if you can change send to just actually take Helper objects, you don't need to allocate it at all, you can just pass it by value.
It also occurs to me that you could pack some other data in that pointer to pass other data in-place, but that'd be abi hacking and possibly undefined behavior. Try it if you wanna play though :)
If you have a class called 'Rock', and you do something like :-
int main()
{
Rock;
}
why do you get "declaration does not declare anything" error ?
Shouldn't it just call the default constructor and create the object at that moment?
Ofcourse I won't be able to use that object and it will get destroyed when it will go out of scope of the function, but why not creating it at all?
In some other programming languages like java, variables are not compulsory. you can do something like new Rock() and you will be fine.
I know it isn't of any use but I want to clear my confusion.
Rock is just the name of the class. There is no variable name declared. To call a constructor/create an object, you need to declare the name of a variable: Rock r;
This creates an object on the stack that will get destroyed when it goes out of scope
Rock;
This instantiation code is wrong.
If it has to call default constructor you have to name the object as follows.
Rock rd;
In C++ Rock is a custom type.
So to define the variable of type Rock, you have to follow the syntax as follows
Typename variableName
In Java, calling new Rock(); will create a temporary object which might get garbage collected right away since it's not bound to a reference.
In C++, you can do the same thing with Rock{};, except now you have the guarantee that the object will be destroyed right away
You can do :
Rock();
But what's the goal of that ?
If you want to call the constructor use
Rock( )
Though I don't see much use for what you're trying to do here.
You're basically just stating a type without an actual object.
Rock *someRock = new Rock( );
Is legit in C++ as well as it creates an object on the heap rather than the stack. ( Note you have to free the memory once the object is no longer needed with delete someRock; )
Example
To make this a declaration or an expression you have two posiibilities. The first one is indeed a declaration
int main()
{
class Rock;
}
This declaration declares (or redeclares) class Rock in the scope of function main.
And the second one creates a temporary objects of the class calling its default constructor
int main()
{
Rock();
}
Constructors are called using the function call syntax.
Take into account that in C++ you also may use operator new. However the value returned by the operator should be assigned to a pointer. Otherwise there will be a memory leak. The C++ does not have a garbage collector.
So insetad of
new Rock();
you should write
Rock *r = new Rock();
Or you may even redeclare name Rock the following way
Rock *Rock = new class Rock();
I am trying to write a function that will check if an object exists:
bool UnloadingBay::isEmpty() {
bool isEmpty = true;
if(this->unloadingShip != NULL) {
isEmpty = false;
}
return isEmpty;
}
I am pretty new to C++ and not sure if my Java background is confusing something, but the compiler gives an error:
UnloadingBay.cpp:36: error: no match for ‘operator!=’ in ‘((UnloadingBay*)this)->UnloadingBay::unloadingShip != 0’
I can't seem to figure out why it doesn't work.
Here is the declaration for class UnloadingBay:
class UnloadingBay {
private:
Ship unloadingShip;
public:
UnloadingBay();
~UnloadingBay();
void unloadContainer(Container container);
void loadContainer(Container container);
void dockShip(Ship ship);
void undockShip(Ship ship);
bool isEmpty();
};
It sounds like you may need a primer on the concept of a "variable" in C++.
In C++ every variable's lifetime is tied to it's encompassing scope. The simplest example of this is a function's local variables:
void foo() // foo scope begins
{
UnloadingShip anUnloadingShip; // constructed with default constructor
// do stuff without fear!
anUnloadingShip.Unload();
} // // foo scope ends, anything associated with it guaranteed to go away
In the above code "anUnloadingShip" is default constructed when the function foo is entered (ie its scope is entered). No "new" required. When the encompassing scope goes away (in this case when foo exits), your user-defined destructor is automatically called to clean up the UnloadingShip. The associated memory is automatically cleaned up.
When the encompassing scope is a C++ class (that is to say a member variable):
class UnloadingBay
{
int foo;
UnloadingShip unloadingShip;
};
the lifetime is tied to the instances of the class, so when our function creates an "UnloadingBay"
void bar2()
{
UnloadingBay aBay; /*no new required, default constructor called,
which calls UnloadingShip's constructor for
it's member unloadingShip*/
// do stuff!
} /*destructor fires, which in turn trigger's member's destructors*/
the members of aBay are constructed and live as long as "aBay" lives.
This is all figured out at compile time. There is no run-time reference counting preventing destruction. No considerations are made for anything else that might refer to or point to that variable. The compiler analyzes the functions we wrote to determine the scope, and therefore lifetime, of the variables. The compiler sees where a variable's scope ends and anything needed to clean up that variable will get inserted at compile time.
"new", "NULL", (don't forget "delete") in C++ come into play with pointers. Pointers are a type of variable that holds a memory address of some object. Programmers use the value "NULL" to indicate that a pointer doesn't hold an address (ie it doesn't point to anything). If you aren't using pointers, you don't need to think about NULL.
Until you've mastered how variables in C++ go in and out of scope, avoid pointers. It's another topic entirely.
Good luck!
I'm assuming unloadingShip is an object and not a pointer so the value could never be NULL.
ie.
SomeClass unloadingShip
versus
SomeClass *unloadingShip
Well, you don't have to write so much code to check if a pointer is NULL or not. The method could be a lot simpler:
bool UnloadingBay::isEmpty() const {
return unloadingShip == NULL;
}
Plus, it should be marked as "const" because it does not modify the state of the object and can be called on constant instances as well.
In your case, "unloadingShip" is an object of class "UnloadingShip" which is not dynamically allocated (except when the whole class "UnloadingBay" is allocated dynamically). Thus, checking if it equals to NULL doesn't make sense because it is not a pointer.
For checking, if an object exists, you can consider going this way:
create a pointer to your object:
someClass *myObj = NULL // Make it null
and now where you pass this pointer, you can check:
if(!myObj) // if its set null, it wont pass this condition
myObj = new someClass();
and then in case you want to delete, you can do this:
if(myobj)
{
delete myObj;
myObj = NULL;
}
so in this way, you can have a good control on checking whether your object exists, before deleting it or before creating a new one.
Hope this helps!