I've came across the following code, ok, not exactly but close.
The point of interest is the second line in the (heavily abbreviated code).
Why does one have to intialize someReference 'someReference' ? Other then be able to use . operator instead of -> ?
ptrThis is just as good, no? (it's inside the thread method, if that makes any difference)
// this line, why?
SomeClass & someReference(*ptrThis);
unsigned SomeClass::someThread(void *ptr)
{
SomeClass *ptrThis = reinterpret_cast<SomeClass*>(ptr);
SomeClass & someReference(*ptrThis);
// some other code
}
References always need to be initialized when they're declared (unless they're external). They remain bound to one object during their whole lifetime. This ensures that a reference, unlike a normal pointer, can (theoretically) never be NULL because it must refer to somebody. Assigning to a reference assigns to the referencee.
Yes; ptrThis is just as good. Matter of style, I suppose. It does seem a bit redundant given what you've posted, but I'll give the original author the benefit of the doubt that it made sense in the context of the full example.
It doesn't have to do anything related to threads and as such cant interpret much from what code snippet which you have given
Related
I'm getting to grips with references in C++ and I have a small query surrounding references & scoping, for this it's probably best to create an example:
Imagine I have a method in "BankDatabase.cpp" which takes a bank record by reference and adds it to a data structure (also by reference).
void AddRecord( BankRecord& bankRecord )
{
//Add record to data structure by reference
}
If I run a method like so:
void TestAddRecord( BankDatabase& bankDatabase )
{
BankRecord bankRecord { "John", "Doe", 9999 }
bankDatabase.AddRecord( bankRecord );
}
To my mind, "bankRecord" falls out of scope (as do its two strings and int) and is thus cleared from memory at the end of the "TestAddRecord" method, leaving "bankDatabase" pointing at some empty memory?
If so what's the general accepted standard / resolution to such a scenario? It seems a little mad to have to pass things by value...
In that case passing by value seems like the way to go. Allocating a new BankRecord pointer will work too. Storing things by reference is not very great.
However if I'm not mistaking, your two strings and the int won't be lost since they are present in the stack and will not be deallocated. But bankRecord will still be lost.
The best way to answer these concerns is to step through the code in the debugger and see what the Vector is doing with the variable being appended. Look especially at the constructor calls as you step into the data structure's Append functions. Because I do not know your underlying data structure, it is a bit more difficult for me to tell you more information. I will assume it is a std::vector for now until told otherwise.
You may be surprised to learn that references passed through a function do not tell the entire story about when it will go in and out of scope. I often think of C++ references as pointers that do not need nullptr checks.
Your code will work fine as long as the reference is copied into the vector or does not go out of scope because the variable it pointed to was destroyed. The reference will not go out of scope if it is referring to a member variable or memory on the heap for your particular case.
If the reference was declared on the stack to a variable created on the stack, and then appended to the vector, then you will have scope problems.
You should also look into emplace() if you have C++11 and the compiler supports move semantics.
In short, the most important thing you can do here is step through the code and see what Constructors are being called. This will give you the answer you desire.
I have been attempting to learn C++ over the past few weeks and have a question regarding good practice.
Let's say I have a function that will produce some object. Is it better to define the function to produce an output of type object, or is it better to have the function be passed an object pointer as an argument such that it can modify it directly?
I suppose this answer is dependent on the scenario, but I'm curious if efficiency comes into play. When passing objects into a function as an argument, I know it is more efficient to use const reference such that the function has immediate access to the object with no need of generating a copy.
Does such concern of efficiency come into play when outputting function results?
The following:
MyType someFunc()
{
MyType result;
// produce value here
return result;
}
Used like this:
MyType var = someFunc();
Will do no copy, and no move, but rather RVO.
This means that it can't get more efficient anyway, and it is
also easy to read, and hard to use wrong. Don't help the compiler.
You can return created object as a pointer or shared pointer from function. This is useful for immediate checking return value.
std::shared_ptr<Object> CreateObject(int type)
{
if (type == SupportedType)
return std::make_shared<Object>();
else
return std::shared_ptr<Object>();
}
...
if (std::shared_ptr<Object> object = CreateObject(param))
// do something with object
else
// process error
This is more compact way than passing reference to object's pointer as param and maybe a bit more intuitive.
By passing things by reference you are saving memory resources, this will prevent you from creating copies of things when not needed.
I find it is good practice to pass everything as constant pointers initially and go back and change if needed. This makes sure you are really aware of the structure of your code.
As the best practice, often having easy-to-read code is the most important factor. See what method makes that block of code easier to read and go that way. In most cases the answer by sp2danny is the clearest.
If for your project the speed has the highest priority then test all the possible methods and see which one is faster. Because most likely your code is more complicated than calling a single function and getting an object back, and probably a few other functions interact with that object too. Hence, you should consider the whole code while trying to improve the speed.
So after working on my last question, I boiled it down to this:
I need to add an unknown number user-defined classes (object_c) to a boost::intrusive::list. The classes have const members in them. All I need to do to push them to the list is to construct them and then have them persist, they automatically add themselves.
The code in question is basically
for (unsigned i = 0; i < json_objects.count(); ++i) {
ctor_data = read(json_objects[i]);
// construct object here
}
What I've tried:
mallocing an array of objects, then filling them in: Doesn't work, because I have const members.
static object_c *json_input = (object_c*) malloc(json_objects.size() * sizeof(object_c));
...
json_input[i](ctor_data); //error: no match for call to (object_c) (ctor_data&)
Making a pointer: This doesn't work, functions don't work properly with it, and it doesn't get destructed
new object_c(ctor_data);
Pushing the object back to an std::vector: This doesn't work, boost rants for dozens of lines when I try (output here)
vector_of_objects.push_back(object_c(ctor_data));
Just declaring the darn thing: Obviously doesn't work, goes out of scope immediately (dur)
object_c(ctor_data);
I'm sure there is an easy way to do this. Anyone have any ideas? I've been at this problem for most of the weekend.
#3 should be the method you need to use. You need to elabourate on what your errors are.
If it is just operator= as you show in your previous question, and you dont want to define one, you can try emplace_back as long as you are in C++11. Of Course I am talking std::vector, I need to check what is the equivalent if any in boost::intrusive. Edit: I might be wrong, but it doesnt seem to support move semantics yet..
Alternatively use #2 with smart pointers.
If you are going with #1, you would need to use placement new as #rasmus indicates.
At the end of the documentation's usage section it tells you that
“The lifetime of a stored object is not bound to or managed by the container”
So you need to somehow manage the objects’ lifetime.
One way is to have them in a std::vector, as in the documentation’s final example.
Sorry for the late reply, exam studying and all that.
It was simpler than I was making it out to be, basically. Also, for this answer, I'm referring to my class as entity_c, so that an object of entity_c actually makes sense.
What I was doing in my OP was when I push_back'd an entity_c, it was automatically adding itself to a global intrusive::list, and somehow that made it not work. After I stopped being lazy, I wrote up a minimal compilable progam and played around with that. I found out that making an std::vector to store the constructed entity_cs in worked (even though it deconstructs them when they're added? I dunno what that's about). Then all I had to do was populate a local intrusive::list with those objects, then clone the local list into the global list.
Thanks for all the help, I'll tweak that program to try and fit in different stuff, like placement new suggested by #rasmus (thanks for that, hadn't seen that before). Also thanks to #karathik for showing my emplace_new, I think I might have to go and find out about all these new C++11 features that have been added in, there are so many cool ones. I even learnt how to make my own copy constructor.
Truly and edifying educational experience.
I have been teaching myself C++ in the last few days, and have run into some situations that I could use some further explanation on. What is the difference between the following methods besides the obvious class, naming, etc?
void OnTimer(wxTimerEvent &event) ...
void addNPC(Sprite *spr) ...
Are both those methods receiving values passed by reference and doing the same thing? If so, what is the difference? When I first started reading, I saw the method called like this:
addNPC( &sprite );
So I assumed that when you wrote a method that would be receiving a memory pointer, in the method arguments you must write it like you were declaring a memory pointer/location, and not just a value. But then I look at the OnTimer method, and I see that it also has a reference being passed. What's the difference?
Finally, are these two things the same, and just actual coding styles?
void addNPC(Sprite& spr) ...
void addNPC(Sprite &spr) ...
Last question first: the two function prototypes are equivalent. Whitespace is mostly not significant in C or C++.
As for the difference between references and pointers, think of a reference as "syntactic sugar" for a pointer, with the additional restriction that it cannot be NULL. For more on this, see the C++ FAQ: https://isocpp.org/wiki/faq/references
void addNPC(Sprite *spr)
In above code, you need to pass address of Sprite object like below, as it receives pointer.
addNPC( &sprite );
And for the function
void OnTimer(wxTimerEvent &event)
call has to be like below as it takes reference to wxTimerEvent object.
wxTimerEvent evt;
OnTimer(evt);//Passing object by reference.
At calling place, Syntax is same for
both pass by value and pass by
reference.
And for your last question, they both are same, just the coding style difference.
wxTimerEvent &event is a reference to an object. It acts like and looks like a normal variable but it references a variable outside of the function. Any changes made to the local references are actually changing the original. It is essentially a pointer that you can access as a normal variable and it cannot be NULL.
Sprite *spr is a real pointer to an outside variable. Any changes made to it locally are also made outside the function. It can be NULL!
The last two items are identical. Spaces are not significant in C/C++ code.
In addition to other answers there is one feature of const reference - you can assign temporary object to it and object will live as long as const reference is alive.
string its_alive();
void foo() {
const string& some_string = its_alive();
...
}
So you use references if the user of the reference not responsible for object's destruction AND if NULL object makes no sense.
Here's honorary GotW #88 for explanation of const reference to temporary object.
i am passing HBuf to function
but it crashes i don't know whether i am following right way or not
//case 1:
HBufC8* iBuffer2 = HBufC8::NewL(1000 );
TPtr8 bufferPtr( iBuffer2->Des() );
//assigning value to HBuf code
StartParsingL(iBuffer2);
StartParsingL(HBufC8* aHBufPtr)
{
iBuffer = HBufC8::NewL(aHBufPtr->Length());//it crashes here
bufferPtr.Copy(aHBufPtr->Des());//also here
}
Not answering your question (as there isn't really enough information). I would recommend using an RBuf instead of a HBuf as they are the recommended heap buffer descriptor going forward, and a bit easier to use.
In the Symbian coding convention, "i" prefixed variables are member variables.
In your snippet you have it as a local declaration. It could be that you just put in the type for clarity of the snippet, but if you've declared it both as a member variable and as a local declaration, that could explain plenty of crashes :-)
You should have:
class C....: public CBase?....
{
private:
HBufC8* iBuffer2;
};
...
void C...::ConstructL()
{
...
iBuffer2 = HBufC8::NewL(1000);
...
}
This code does not directly show the reason for crashing. Please post actual snippets next time.
Also, when posting about a crash, it is good to know how it is crashing. I assume it is a KERN-EXEC 3 panic. But please be explicit about it yourself.
I guess the aHBufPtr passed to StartParsingL is either zero or otherwise does not point to a valid HBuf8 object. That would be the immediate reason for the crash. Why it is not a valid pointer is not visible in the code, but one reason could be shadowing a member variable with a local variable as suspected by #Will.
Some further points, not related to crash here but Symbian C++ in general:
When passing descriptors around, you should use the most general read-only TDesC or TDesC8 type references or read-write TDes or TDes8 type references. Use HBufC or HBufC8 pointers only if you are transferring ownership to the callee.
In this snippet:
bufferPtr.Copy(aHBufPtr->Des());
Copy accepts a TDesC& so you do not need to call Des:
bufferPtr.Copy(*aHBufPtr);
Though if you just want to copy a descriptor, you could use any of the descriptor Alloc functions such as AllocL.