I have a routine that gets passed a void* to a structure. In the
routine I cast it to the correct type, e.g.
SomeFunc(void* pMsg) {
printf("Event = %d\n", static_cast<struct MyEventMsg*>(pMsg)->Event);
}
If I am accessing many members of the structure the code looks pretty
messy. I can create a new pointer of the correct type and assign it
the cast void*, but it seems like it shouldn't be necessary to create
a temporary variable just for this purpose. Is there some way to cast
the parameter pMsg to the correct type?
Thanks
Doug
Creating the pointer of the correct type and assigning it the cast of the void* is the correct way to go. It will make the code shorter and easier to read, if you choose a "good" name for the pointer.
You say that you think the pointer "unnecessary". If this is because you think that there is a run time cost associated with it, you may well find out that the compiler will eliminate the pointer for you.
The way to do what you ask is
SomeFunc(void* pMsg) {
MyEventMsg * pM = static_cast<struct MyEventMsg*>(pMsg);
printf("Event = %d\n", pM->Event);
printf("Something Else = %d\n", pM->SomeOtherMember);
...
}
But I would recommend something more C++:
SomeFunc(MyEventMsg &Msg) { // consider making this const
cout << "Event = " << Msg.Event << endl;
cout << "Something Else = " << Msg.SomeOtherMember << endl;
...
}
No, as a matter of fact it should be. Static cast is your best option. Don't worry about the temporary. It will most likely be optimized away by your compiler
Just go with the temporary. If you manage everything properly (if any managing is even needed), it won't cause you any problems. I'd imagine making the temp will be faster as well since you'd only be making one cast as opposed to casting EVERYTIME for EVERY member of the struct.
The first question is why does the function take a void* in the first place. If that is changed to the exact type of pointer, then the problem goes away altogether.
If you are going to use the pointer (after casting to the appropriate type) more than once in the function, I would just create a local variable of the given type, cast once and then use it. As of the cost of creating such a variable, in many cases the compiler will optimize the variable away (if you doubt, look at the generated assembly).
but it seems like it shouldn't be necessary to create a temporary variable just for this purpose
Um, it's not: like you said, you can do a cast in-place.
Make your choice: cast every time (messy) or cast once into a variable of the correct type (clean).
Change the type of pMsg to struct MyEventMsg * and create a second, inline version of the method that takes a void *, casts it and calls the first one.
You can prevent calls to the first method by making it private.
Related
Best explained with an example:
Class banana {
int &yumminess;
banana::banana() {
//load up a memory mapped file, create a view
//the yumminess value is the first thing in the view so
yumminess = *((int*)view);
}
}
But that doesn't work :/ there is no way I can know where the view is going to be when I dreclare the "yumminess" reference variable. Right now i just use a pointer and dereference it all the time, is there any way to bring this little extra bit of convenience to my class?
In short: No, it's intentionally not possible.
Think twice: Something like uninitialized references cannot really exist; such wouldn't make sense at all.
Thus they'll need to be set at the time of construction of the enclosing class, or at a point of static initialization.
You'll need to use pointers for such case.
Besides note that
yumminess = (int*)view;
would be wrongly casted (to a pointer) anyway.
"Right now i just use a pointer and dereference it all the time ..."
That's also easy to overcome writing an appropriate member function to access the reference.
int* yumminess;
// ...
int& yumminessRef() {
if(!yumminess) {
throw some_appropriate_exception("`yumminess` not initialized properly.");
}
return *yumminess;
}
No, not directly.
If you think the pointer is inconvenient, have a look at std::optional.
In following example const object can modify itself via const method, because in that method it acces itself via non-const pointer. (same program on ideone)
#include <iostream>
struct Object;
Object * g_pObject;
struct Object
{
Object():m_a(0){}
void ModifySelfViaConstMethod() const
{
g_pObject->m_a = 37;
}
int m_a;
};
int main()
{
Object o;
g_pObject = &o;
const Object & co = o;
std::cout << co.m_a << "\n";
co.ModifySelfViaConstMethod();
std::cout << co.m_a << "\n";
return 0;
}
I am not so good with reading c++ standard, so I ask here:
What does standard says about this?
a)const method doesn't guarantee you that your object stays unmodified when you do stuff like this
b) Is it well defined that and it must compile
c) other ?
When you declare a const function, it's "for your own good".
In other words, you declare it const because according to your initial design, it is not supposed to change any object with which it will be invoked during runtime.
If during some later point in the implementation of this function you end up changing the object, the compiler will "yell at you", telling you it's wrong.
Of course, the compiler will be able to identify such attempt, only when applied on this.
In the given example, the compiler cannot identify the problem because it requires a comparison between this and g_pObject, and such comparison can only take place during runtime.
When a method is declared as const, the compiler ensures that the instance pointed to by the this pointer is not modified. If you try to modify the this instance, the compiler to fail. However, the compiler has no way of knowing that g_pObject and this are actually pointing at the same instance. That requires a run-time comparison, and no compiler is going to waste time performing run-time comparisons of every pointer used inside of a const method in the off-chance that they might match the this pointer. So if you are going to modify an Object via an external pointer, you are going to have to do your own check, eg:
void ModifySelfViaConstMethod() const
{
if (g_pObject != this)
g_pObject->m_a = 37;
}
What does standard says about this?
It says (paraphrasing) that this has type const Object *, so that you can't directly modify members or call non-const member functions via this. It says nothing about what you can do with any global variables that the function might have access to; it only controls direct access to the object the function is called on.
const method doesn't guarantee you that your object stays unmodified when you do stuff like this
No it doesn't. It states the intent that the function won't modify the object, and provides some protection against accidentally breaking that intent. It doesn't prevent a suitably deranged programmer from using const_cast, or (as here) uncontrolled coupling via global variables to break the promise.
Is it well defined that and it must compile
Yes. o is not itself constant, so there's nothing to stop you taking a non-const pointer or reference to it. The const on the member function only restricts access to the object via this, not to arbitrary objects via other pointers.
Constancy in C++ is a safety instrument, not security.
The code where constancy is honored will most probably work as expected, and all unintentional attempts to cast constancy away will be alerted by the compiler.
In cases when "I know what I am doing" one can find the whole variety of tools, from const_cast operator and mutable keyword to the banal C style cast.
Is there a way to change what THIS point to?
class foo{...}
foo* fooinstance = new foo();
foo* otherfooinstance = new foo();
void
foo::bar(){
this = otherfooinstance;
}
fooinstance->bar();
for those of you who are wondering in what case I would change the this pointer here is case. I had to do a tree recursion where I had to remove intermediate nodes.. for this example lets assume the intermediate nodes of removal have the title d. and these intermediate nodes only have one child. So in lisp notation if we have a tree like
(g (d (i 4)) (i 5))
the function removeIntermediates(tree) would in effect cause the above to become
(g (i 4) (i 5))
and the pseudo code for this IF the this pointer was reassignable would look like the following..
DTREE::removeIntermediates(){
this = child(0); removeIntermediates();
}
TREE::removeIntermediates(){
for each child { child->removeIntermediates();
}
I wanted to do this without knowing what the child node was therefore making code factorable into different functions for each node type and having a general function for other types.
Sadly, I just ended up doing something like this..
TREE::removeIntermediates(){
for each child { if(child->name == "d") {
setchild(child->child(0));
child->removeIntermediates();
}
else { child->removeIntermediates();}
}
No, this is not modifiable.
Conceptually that doesn't make sense, what are you trying to accomplish?
C++ standard forbids assignment to this in "9.3.2 The this pointer" by stating that "keyword this is a non-lvalue expression". Although, some compilers still allow assignment to this by using a certain compile-time switch, because at some point in early drafts C++ standard actually allowed assignment to "this".
Anyway, it is quite hard to imagine a case where you would actually want to do that and it is very likely that there is a clean and beautiful way to do it.
No, you should never, ever, set this.
If you need to point to different objects then define your own variable.
No. This is an rvalue, not an lvalue. The easiest way to think
of it is that it invokes compiler magic to access the object on
which the function was called. You can't modify it any more
than you could modify the constant 3.
Historically, in very early versions of C++, you could modify
it, but only in the constructor, and only as the first thing in
the constructor: the functionality offered by this has been
subsumed by user defined operator new. This was 20-15 years
ago, however.
What are you trying to do? If you just want to access two
different objects from the same member function, that's no
problem: otherfooinstance-> should work, and will give you
access to the private members as well.
The member method void foo::bar() { this = otherfooinstance; } will be compile like this:
void foo__bar(foo * const this) { this = otherfooinstance; }
this is a const pointer to calling foo instance, so you can't change it.
And change this is not a good idea.
The "this" pointer doesn't really exist. That is, it's not stored somewhere with the object. Rather, when a method is called on an object the compiler passes the address of the object as an extra argument. So "this" only ever really appears on the stack while a method is executing.
So even if you did assign to "this" as in your example, your redirection to otherfooinstance would last only for the duration of the current bar() invocation.
Can you give me an example when I can't pass argument by reference and I need to use pointer. I've found an example, but I'm not sure.
Suppose you have a class D derived from the base class B. You need pointer if you want do so:
void function(B* b){...}
int main{
D* d;
function(d);
}
The single time where you can not use a reference and must use a pointer is if you allow the concept of "no argument" by passing a null pointer.
However, you might want to use pointers as arguments when you are actually storing a pointer to whatever was passed. Most C++ developpers will notice that you aren't using a reference and pay special attention to what your documentation says.
If there is a coding guideline (like Google's) that says to use pointer arguments, then that's what you do.
Otherwise, only declare your own function with pointer formal argument when
a nullpointer is a valid & meaningful actual argument, or
the actual argument is most naturally pointer already, or
you're going to store that pointer somewhere.
Possibly more cases, but I think you get the drift: when you have a choice (no coding guideline saying otherwise), prefer references.
Cheers & hth.,
Another case: if the thing you're passing is the last argument before varargs:
void fn1(A &a, ...); // Uh oh
void fn2(A *a, ...); // Good
I don't know if this is required by the standard, or is just a bug in the implementation of the C++ compiler I use.
Typically, you use pointers for one of two things:
Reassignability - you can't rebind a
reference.
Null pointers - there's no such
thing as a null reference.
If your intended use case does not need either of those two properties, use a reference. Else, use a pointer.
If you want to allow the lack of an object, you need to use pointers:
// This allows DoSomething to receive pointers to NULL, which cannot
// be done with references
void DoSomething(Something *pSomething)
{
if (pSomething)
{
...
}
}
int main()
{
Something *pSomething=NULL;
DoSomething(pSomething);
}
http://www.daniweb.com/forums/thread216353.html
Singly linked lists example were pointers and pointer of pointers are used as function parameters.
the only reason is if you need to pass null. I.e you want to call the function saying 'I haven't got one of those'
I think that if you want to pass a function, you have to pass it by pointer. I don't see how you can pass the function by reference.
For example, take the following function:
#include <iostream>
#include "math.h"
void myfun (double value, size_t nofloops, double (*function)(double))
{
std::cout << value << std::endl;
for (size_t i=0;i<nofloops;++i)
{
value = function(value);
std::cout << value << std::endl;
}
std::cout << "------------------" << std::endl;
}
void main()
{
myfun(100,10,sin);
myfun(100,10,cos);
myfun(100,10,sqrt);
}
The function in this small utility executes the given function a number of times, taking the result as input in the next iteration. I can't see how you can pass the function by reference.
Today I stumbled over a piece of code that looked horrifying to me. The pieces was chattered in different files, I have tried write the gist of it in a simple test case below. The code base is routinely scanned with FlexeLint on a daily basis, but this construct has been laying in the code since 2004.
The thing is that a function implemented with a parameter passing using references is called as a function with a parameter passing using pointers...due to a function cast. The construct has worked since 2004 on Irix and now when porting it actually do work on Linux/gcc too.
My question now. Is this a construct one can trust? I can understand if compiler constructors implement the reference passing as it was a pointer, but is it reliable? Are there hidden risks?
Should I change the fref(..) to use pointers and risk braking anything in the process?
What do you think?
Edit
In the actual code both fptr(..) and fref(..) use the same struct - changed code below to reflect this better.
#include <iostream>
#include <string.h>
using namespace std;
// ----------------------------------------
// This will be passed as a reference in fref(..)
struct string_struct {
char str[256];
};
// ----------------------------------------
// Using pointer here!
void fptr(string_struct *str)
{
cout << "fptr: " << str->str << endl;
}
// ----------------------------------------
// Using reference here!
void fref(string_struct &str)
{
cout << "fref: " << str.str << endl;
}
// ----------------------------------------
// Cast to f(const char*) and call with pointer
void ftest(void (*fin)())
{
string_struct str;
void (*fcall)(void*) = (void(*)(void*))fin;
strcpy(str.str, "Hello!");
fcall(&str);
}
// ----------------------------------------
// Let's go for a test
int main() {
ftest((void (*)())fptr); // test with fptr that's using pointer
ftest((void (*)())fref); // test with fref that's using reference
return 0;
}
What to you think?
Clean it up. That's undefined behavior and thus a bomb which might blow up anytime. A new platform or compiler version (or moon phase, for that matter) could trip it.
Of course, I don't know what the real code looks like, but from your simplified version it seems that the easiest way would be to give string_struct an implicit constructor taking a const char*, templatize ftest() on the function pointer argument, and remove all the casts involved.
It's obviously a horrible technique, and formally it's undefined behaviour and a serious error to call a function through an incompatible type, but it should "work" in practice on a normal system.
At the machine level, a reference and a pointer have exactly the same representation; they are both just the address of something. I would fully expect that fptr and fref compile to exactly the same thing, instruction for instruction, on any computer you could get your hands on. A reference in this context can simply be thought of as syntactic sugar; a pointer that is auto-dereferenced for you. At the machine level they are exactly the same. Obviously there might be some obscure and/or defunct platforms where that might not be the case, but generally speaking that's true 99% of the time.
Furthermore, on most common platforms, all object pointers have the same representation, as do all function pointers. What you've done really isn't all that different from calling a function expecting an int through a type taking a long, on a platform where those types have the same width. It's formally illegal, and all but guaranteed to work.
It can even be inferred from the definition of malloc that all object pointers have the same representation; I can malloc a huge chunk of memory, and stick any (C-style) object I like there. Since malloc only returned one value, but that memory can be reused for any object type I like, it's hard to see how different object pointers could reasonably use different representations, unless the compiler was maintaining an big set of value-representation mappings for every possible type.
void *p = malloc(100000);
foo *f = (foo*)p; *f = some_foo;
bar *b = (bar*)p; *b = some_bar;
baz *z = (baz*)p; *z = some_baz;
quux *q = (quux*)p; *q = some_quux;
(The ugly casts are necessary in C++). The above is required to work. So while I don't think it is formally required that afterwards memcmp(f, b) == memcmp(z, q) == memcmp(f, q) == 0, but it's hard to imagine a sane implementation that could make those false.
That being said, don't do this!
It works by pure chance.
fptr expects a const char * while fref expects a string_struct &.
The struct string_struct have the same memory layout as the const char * since it only contains a 256 bytes char array, and does not have any virtual members.
In c++, call by reference e.g. string_struct & is implemented by passing a hidden pointer to the reference so on the call stack it will be the same as if it was passed as a true pointer.
But if the structure string_struct changes, everything will break so the code is not considered safe at all. Also it is dependent on compiler implementation.
Let's just agree that this is very ugly and you're going to change that code.
With the cast you promise that you make sure the types match and they clearly don't.
At least get rid of the C-style cast.