this might be stupid question, but:
When I moved from ASM to C (no, I am not actually that old, I just started to love programing on MCU), I LOVED the way heap memory is used. Malloc was my friend, and I quickly became familiar with pointers. BUT...
Than I moved to OOP and Java. And actully, despite I donĀ“t like Java as a runtime, I love its language. Now, I would like to combine both, speed and memory management capabilities of C and the beauty of OOP. So I started to learn C++.
My problem is, in Java I was used to access class members and functions with . operator. In C++, I have to use somehow not so nice and easy to type -> operator.
So, my question is, is there some way you can use . operator instead of -> to access class members of object allocated on heap? Becouse, stack is limited, and the true power of OOP is in dynamic creation of objects. Remaining "differences" are OK :) . Well, maybe C++ yould allow you to define class methods inside class, but no one can have everything, right? :D Thanks.
Class &c = *c_ptr; // dereference pointer
https://isocpp.org/wiki/faq/references
Sure. Just get a reference to some object allocated on the heap (or the stack, but that's beyond scope):
Object* my_obj_ptr = SomehowGetHeapObject();
Object& my_obj = *my_obj_ptr;
...then you can use the dot operator on the reference:
my_obj.Foo();
Perhaps a pertinent question would be, why is this throwing you off?
No, that is not posssible, at least without some syntax changes. You can use (*Pointer).Function, which Pointer->Function is just a synonym for, but I think the latter is more comfirtable (that's why it exists).
EDIT: Or as the other posts say, just store the dereferenced pointer in a reference. Haven't thought about that, as the whole question is a bit strange.
In C++ there are two ways to access members of an object, depending upon how you are holding the object. If you have the object directly (or have a reference to it), you use the dot operator, .. If you have a pointer to the object, you use the pointer operator ->.
Consider:
class C;
...
// creates a new copy of "c" on stack
int f(C c) {
c.something = c.else;
}
// creates a reference to caller's "c"
int f(C& c) {
c.something = c.else;
}
// creates a pointer to caller's "c"
int f(C* p) {
c->something = c->else;
}
So, your problem is this: you have a pointer, but you don't like the pointer operator. Frankly, I don't really see this as a problem, you should just use the pointer operator until you like it. But, this is SO, so here is a solution.
Initialize a reference from your pointer, and use the reference instead:
int f(C* p) {
C& c = *p;
c.something = c.else; // update the object pointed to by 'p'
}
Or, to make it feel even more natural:
int f2(C& c) {
c.something = c.else; // updates f1's object
}
int f1() {
C* p = new C;
f2(*p);
delete p; // don't forget this step!
}
Related
Object A has method B(), and lives for most of the life of the application. B calls object C method D(). D() returns an array holding up to x MyData objects. MyData might be a POD (plain old data)/PDS (passive data structure) or might be more, but a MyData can be reused by calling methods or setting fields; its identity or functionality isn't cast in stone during construction or otherwise.
Currently B() is defined like:
class A {
public B() {
MyData[] amydata = c.D( 5 );
:
:
}
}
Currently D() is defined like:
MyData[] D( int iRows ) {
MyData[] amydata = new MyData[ iRows ];
for ( int i = 0; i < iRows; i++ ) {
if ( no more data )
return amydata;
amydata [ i ] = new MyData();
// calculate or fill in MyData structure.
}
return amydata;
}
A is going to be always, or for a long time (e.g., until the user reconfigures it) be asking for the same number of rows, even though the data will differ.
So what if I have the caller pass in the array reference:
class A {
int iRequestSize = 5;
int iResultSize;
MyData[] amydata = new MyData[ iRequestSize ];
public B() {
iResultSize = c.D( iRequestSize, amydata );
:
:
// use up to iResultSize even though array is potentially bigger.
}
}
// returns number of rows actually used
int D( int iRowsMax, MyData[] amydata ) {
for ( int i = 0; i < iRowsMax; i++ ) {
if ( no more data )
return i;
if ( amydata [ i ] == null )
amydata [ i ] = new MyData();
// calculate or fill in MyData structure.
}
return iRowsMax;
}
I'm a C++ guy and new to Java, but it seems that assuming MyData can be recycled like this, the second version should avoid creating and copying MyData's, as well as eliminating garbage collection?
I would say the second variant is worse.
In the first variant amydata and all the objects referenced by it can be garbage collected as soon as the method B() exits (assuming that B doesn't store a reference to amydata somewhere else.)
In the second variant amydata cannot be garbage collected as long as the instance of A lives.
Consider the case where upon the first call to D() it returns 5 references to MyData objects, but on subsequent calls it returns no more rows. In the first variant the amydata array and the 5 referenced MyData objects can be garbage collected as soon as B() returns. But in the second variant neither the amydata array nor the 5 MyData objects referenced through it can be garbage collected - possibly never during the whole runtime of your application.
Remember: the Java Garbage Collector is optimized for many short-lived objects
Disclaimer: Reading the OP's comments, I have to admit that I didn't get his real intent, i.e. to develop a soft-real-time application, avoiding garbage collection as much as possible, a very special and rare situation in the Java world.
So the following answer does not match his problem. But as a casual reader migrating from C++ to Java might stumble over this question and answer, he/she might get some useful hints on typical Java programming style.
Although the syntax of Java and C++ have quite some similarities, because of the very different runtime environments, you should adopt a different coding style.
As a decades-long Java guy, I'd surely prefer the original method signature. As a caller of the D() method, why should I create the results data structure instead of getting it from the method I am calling? That reverses the natural flow of data.
I know, in good old C times when dynamic memory management meant lots of headache, it was very common to prepare the result array outside of the function and have the function only fill in the results, the way you wrote the second version. But forget about that with Java, and just let the garbage collector do its job (and it's very good at that job). Typically trying to "help" the GC results in code that's in fact less efficient and harder to read. And if you really want to stick to that style, there's no need to pass both the max rows number and the array, as the array itself knows its length (that's different from old-style C arrays), giving the max row number.
You assume
the second version should avoid creating and copying MyData's
That sounds like a misconception about Java's inner workings. Every time you execute a new MyData(...) expression, you create a new instance somewhere on the heap. Providing a MyData[] array doesn't avoid that. Translated to C terminology, the array just holds pointers to MyData objects, not the real objects. And Java instances are hardly ever copied (unless you explicitly call something like object.clone()). It's just the reference (= pointer) to the instance that gets copied when you assign something to a variable.
But even the first version is far from perfect, if I understand its purpose correctly. The D() method itself can determine when there's no more data available, so why should it return an array longer than necessary? With Java arrays that's a bit inconvenient, so typical Java code returns a List<MyData> in similar situations.
One more comment on the MyData() constructor and later "calculate or fill in MyData structure". I know that style exists (and is quite popular in the C family of languages), but it's not predominant in Java, and I especially dislike it. To me, it sounds like asking "Give me a car" and getting just a skeleton instead of a usable car. If I want it to have wheels, an engine and seats, I later have to supply them myself. If a usable car needs the selection of options, I want to supply them when ordering the car / calling the constructor, so that I can honestly call the result a car instead of a skeleton.
And finally a comment on the Java naming conventions: the vast majority of Java code follows the conventions, so your method names beginning with upper case look very strange to me.
In Java, when you assign one object to another, the original object isn't copied, it merely clones the reference. So, for example, I'd like it to behave like this Java code:
SomeClass x = new SomeClass();
SomeClass y;
y = x; // x is not copied, y is simply a (Java) reference to x
What I'd like to do is create a C++ class that behaves the same way. The obvious choice is to overload the assignment operator, like so:
SomeClass& operator=(const SomeClass& rhs)
{
this = &rhs;
return *this;
}
Unfortunately, assigning a new location to this is not allowed; the above code won't even compile.
Does anyone know of any other way to do this?
Also, before you say anything: yes, I know this is absolutely the wrong way to implement an assignment operator. Please, indulge me anyway.
EDIT 2: To clarify, here is the C++ code that should behave as in Java:
SomeClass x = SomeClass(); // Created on stack
SomeClass y; // In C++, same as above; NOT reference or pointer
y = x; // x is not copied, y becomes a (C++) reference to x;
// original y is destroyed when stack unwinds
I DO NOT want to use pointers at all.
EDIT: I'm doing this to see if I can change the base address of a C++ object that was passed by reference to a function. If I simply assign another object to the reference variable, it automatically makes a shallow copy, and I don't want that. I want the reference parameter to reference a completely different object.
I'm doing this to see how references are implemented by the compiler. If references are syntactic sugar for dereferenced pointers, then outside the function, the base address of the argument object would NOT change. If they are aliases in the symbol table (as in PHP), then it WILL change. (So any solution using pointers is out, since that's my "control" for the test.)
Hope that makes sense.
This isn't possible. The languages just work fundamentally differently.
SomeClass x in Java is some kind of pointer or reference to a SomeClass object. It's an indirection, so that why you can have multiple ones refering to the same object.
SomeClass x in C++ literally is the object. Thus SomeClass y is literally an entirely different object. There's no indirection. And so there's no way to make one reference the other.
C++ provides pointers (SomeClass* x) and references (SomeClass& x) to take care of the times when indirection is needed. Perhaps those are what you actually want to use, although it depends on why you asked this question in the first place.
Responding to the edit:
No, you can't change the address of an object. An instance of an object will live in exactly one place for the duration of its lifetime, until it is destroyed/deallocated.
I don't think this is okay, because even you assign this to another pointer, then the current object pointed by this will be memory leaked. Java has memory collection, but C++ not.
This is a good question, through. And this is possible.
A& operator=(const A& rhs)
{
A * cthis = const_cast<A*>(this);
cthis = const_cast<A*>(&rhs);
return *cthis;
}
Edit: It is possible to change "this pointer" inside a member function. But changing "this pointer" doesn't accomplish much.
It can be done. but, with pointer indirection.
Lets say you have a class someClass
class someClass
{
someClass *someClsPtr;
public:
someClass(someClass *someClsPtrTemp):someClsPtr(someClsPtrTemp)
{
}
someClass* operator=(someClass *someClsPtrTemp)
{
this->someClsPtr = someClsPtrTemp->someClsPtr;
return this;
}
//now over load operator -> and operator *. Thats it.
};
So I've been thinking (while reading this Java pdf)...
I know this may seem silly but why can't I do this in c++.
float &f = new float;
Isn't this saying the reference of f is the address of new float?
In Java, I see something like this
String s = new String("something")
String s is called a string reference.
Does the word 'reference' in Java have the same meaning as in C++?
Java references are much closer to C++ pointers rather than C++ references. In Java, you can do the following with a reference:
Change which object it refers to
Check whether two references are equal or unequal
Send messages to the referenced object.
In C++, pointers have these same properties. As a result, the code you're looking for in C++ is something like
float* f = new float;
Which is perfectly legal. For a better comparison, this Java code:
String myString = new String("This is a string!"); // Normally I wouldn't allocate a string here, but just for the parallel structure we will.
System.out.println(myString.length());
/* Reassign myString to point to a different string object. */
myString = new String("Here's another string!");
System.out.println(myString.length());
would map to this C++ code:
std::string* myString = new std::string("This is a string");
std::cout << myString->length() << std::endl;
delete myString; // No GC in C++!
/* Reassign myString to point to a different string object. */
myString = new std::string("Here's another string!");
std::cout << myString->length() << std::endl;
delete myString; // No GC in C++!
Hope this helps!
No in Java when you declare String s, s doesnt contain the address of the new String, but its value which in this case is something.
You can take a look at this post for more information about variable address locations in Java which is kind of meaningless.
In C++ you use pointers so if you have:
int foo = 0;
you can then have a pointer refer to the address of foo with:
int* bar = &foo;
This line of code says that the value of bar is foo's memory address.
Java manipulates objects by reference and every object is a reference but it also collects garbage automatically. If you use the new keyword in C++ you need to clean up the memory yourself:
float* f = new float(0); // Allocate memory
...
delete f; // Free memory
Yes, I agree with Joni, a c++ pointer is syntactically closer to a reference in Java.
The other important difference between a pointer and a reference in C++, a pointer can either point to a real object or it can be equal to null. A reference in C++, by definition, always points to a real object or variable. You must assign it to something real when you declare it.
To answer your question, for best practices only use the new or malloc operator to allocate space. Assuming that you are new to pointers, The big difference between pointers and references is that you must use an explicit operator-the * operator-to dereference a pointer, but you don't use an operator to dereference a reference.
Java parameters are close to C++ references. For instance;
When you are passing an object, actually you are passing a reference value. Therefore all objects are references in Java.
On the other hand, Java pass methods by value.
You can also check this link out.
In java reference, you can refer values or methods more than one times. But in c++,you can refer only one value in a single reference variable. So in java reference variables are more likely pointers of c++.Moreover java runs garbage collector automatically, so there is no use of delete key which is used in c++ to release memory.
I just started learning C++ (coming from Java) and am having some serious problems with doing anything :P Currently, I am attempting to make a linked list, but must be doing something stupid cause I keep getting "void value not ignored as it ought to be" compile errors (I have it marked where it is throwing it below). If anyone could help me with what I'm doing wrong, i would be very grateful :)
Also, I am not used to having the choice of passing by reference, address, or value, and memory management in general (currently I have all my nodes and the data declared on the heap).
If anyone has any general advice for me, I also wouldn't complain :P
Key code from LinkedListNode.cpp
LinkedListNode::LinkedListNode()
{
//set next and prev to null
pData=0; //data needs to be a pointer so we can set it to null for
//for the tail and head.
pNext=0;
pPrev=0;
}
/*
* Sets the 'next' pointer to the memory address of the inputed reference.
*/
void LinkedListNode::SetNext(LinkedListNode& _next)
{
pNext=&_next;
}
/*
* Sets the 'prev' pointer to the memory address of the inputed reference.
*/
void LinkedListNode::SetPrev(LinkedListNode& _prev)
{
pPrev=&_prev;
}
//rest of class
Key code from LinkedList.cpp
#include "LinkedList.h"
LinkedList::LinkedList()
{
// Set head and tail of linked list.
pHead = new LinkedListNode();
pTail = new LinkedListNode();
/*
* THIS IS WHERE THE ERRORS ARE.
*/
*pHead->SetNext(*pTail);
*pTail->SetPrev(*pHead);
}
//rest of class
The leading * in
*pHead->SetNext(*pTail);
*pTail->SetPrev(*pHead);
are not needed.
pHead is a pointer to a node and you call the SetNext method on it as pHead->SetNext(..) passing an object by reference.
-> has higher precedence than *
So effectively you are trying to dereference the return value of the function SetNext which does not return anything, leading to this error.
Also, I am not used to having the choice of passing by reference, address, or value, and memory management in general (currently i have all my nodes and the data declared on the heap). If anyone has any general advice for me, i also wouldn't complain :P
Ex-Java programmers always do that. And it's upside down.
You should virtually never heap-allocate data. Objects should be declared on the stack, and if they need heap-allocated memory, they should handle that internally, by allocating it in their constructors and releasing it in their destructors.
That leads to cleaner and safer code.
Class members should also be values, not pointers/references unless you specifically need the member to be shared between different objects. If the class owns its member exclusively, just make it a non-pointer value type. That way it's allocate inside the class itself, and you don't need to keep track of new/delete calls.
The simplest rule of thumb is really to not use pointers unless you have to. Do you need the object to be allocated elsewhere? Why can't it be allocated here and be accessed by value? Even if the object has to be returned from a function, or passed as parameter to another function, copying will usually take care of that. Just define appropriate copy constructors and assignment operators and copy the object when necessary.
What's your deep comprehension of pointer,reference and Handle in C,C++ and Java?
We usually think about the pointer,reference and Handle on the specify language level, it's easy to make confusion by the newbie like me.
Actually all those concept in java, just a encapsulation of pointer.
All pointer just a encapsulation of main memory addresses .
So all of those ,just a encapsulation wiles.
all above, it's my personal glimpse. And what's your comprehension ?
welcome to share with me.
Each language has differences to this respect. In C there are only pointers that are variables holding a memory address. In C you can use pointer arithmetic to move through memory, if you have an array, you can get a pointer to the first element and navigate the memory by incrementing the pointer.
Java references are similar to pointers in that they refer to a location in memory, but you cannot use pointer arithmetic on them. Only assignments are allowed. Note that the reference is not the object, but a way of accessing an object. This can be seen in argument passing semantics: objects are not passed by reference, references are passed by value:
public static void swap( Object o1, Object o2 )
{
Object tmp = o1;
o1 = o2;
o2 = tmp;
}
The previous piece of code is a complex no-op. References to two objects are passed by value, they are played with inside the method and nothing happens from the caller perspective: the real objects do not suffer any change, nor do the references the caller has into those objects. That is, if the call is swap( ref1, ref2 ), the system will make copies of the references into o1 and o2, the copies are changed within the method, but the caller variables ref1 and ref2 will remain unchanged after the method call.
In C++ you have two concepts: pointers are the same as C pointers and close to Java references, while C++ references are aliases into the objects they refer. C++ references can only be initialized with one object/data element in construction and from there on, using the original object and the reference is exactly the same. Besides the fact that references don't hold the resource and thus the destructor will not be called when the reference goes out of scope, nor will the reference notice if the referred object is destroyed, for all other uses the two names are the same element.
template <typename T>
void swap( T & a, T & b )
{
T tmp( a );
a = b;
b = tmp;
}
The code above in C++ differs from the Java version in that it does change the caller objects. If a caller uses swap( var1, var2 ), then the references are bound to those variables, and it is var1 and var2 the ones that suffer the change. After the call, the value of var1 and var2 is actually swapped.
Handles are in a different level, they are not language construct but tokens provided by a library so that you can later on refer to some resource that the library manages internally. The most general case are integer handles that are ids (or offsets) into a resource table, but I have seen strings used as handles. It is the library internally who decides what is exactly a handler (a pointer, an integer, a string or a more complex data structure). Handles are meant to be opaque in that the only sensible use is to store them and later give it back to the same library as part of other function signatures.
In C++ a pointer is a variable that points to a location in memory. You can access the object or data stored there by dereferencing the pointer. A reference is simply a pointer that has two distinctions from a pointer. First, you cannot change what a reference points to once the reference is initialized. Second the dereferencing semantics are removed so you can access a reference as if it were an object allocated on the stack instead of on the heap with new.
In Java, there are no pointers, only references. Every object you use is a reference to an object allocated on the heap. The downside is you can't do pointer math tricks. That's also the upside.
EDIT:
As pointed out in the comments, a Java reference differs from a C++ reference in that it can be reassigned once initialized. They are still called 'reference types' by the language specification, but behaviorally they act like pointers in terms of being able to be reassigned and passed to functions, but the semantics of dereferencing them look like non-pointer access looks in C++.