#include <iostream>
int getID ( int k ) {
static int& r = k;
return r++;
}
int main()
{
int a = getID ( 10 );
int b = getID ( 10 );
std::cout << "a = " << a << ", b = " << b << std::endl;
return 0;
}
I don't understand why this code compiles.
How is it possible for a static reference to refer to a local variable k, which will disappear in the end of the function call).
On the second call we reinitialize the static reference with a new
variable. Please explain what happens here, how come static
REFERENCE can be "redefined" (i guess that i don't understand the
meaning of a reference to a static variable inside a method).
The language does not prevent you from binding references to objects of limited lifespan. That would make it very hard to use references.
(It does prevent you from binding references to temporaries. But a parameter to a function is an l-value, like a local variable, so it's allowed.)
But, if you write code where a reference binds to an object that it outlives, and you keep using the reference, you get undefined behavior, no diagnostic required, and most likely a segfault. It's essentially the same as a dangling pointer in C.
On the second call, you do not rebind the static reference variable to the new temporary. The static variable is only initialized once, the first time the function is called. That line is effectively skipped on all subsequent calls.
If you want a language that would catch mistakes like this for you, and make sure you don't get bitten by dangling references, you could look at Rust. The rust compiler has a "borrow checker" which will check your references for you, without imposing run-time overhead like the many well-known garbage-collected languages will. However Rust does not have static variables so there's no direct translation of that code ;)
In C++, I guess that the above mistake would likely be caught by a static analysis tool like Coverity, which will do some lifetime checking in your code when it scans it. But the C++ compiler won't do it for you, you would need to use a 3rd party tool.
How is it possible for a static reference to refer to a local variable k, which will disappear in the end of the function call).
It's totally possible. You just end up with a dangling reference, which leads to undefined behavior. But the static part isn't significant here.
On the second call we reinitialize the static reference with a new variable. [...]
No, we don't. A static variable is initialized only once. So the second time in getID(), we're still referring to the previous temporary k. Which we then increment, which is undefined behavior. One facet of "undefined behavior" is "code that looks like it works."
Consider a new type:
struct WrappedInt {
~WrappedInt() {
i = 0;
}
int i;
};
and rewrite your code to use it instead:
int getID ( WrappedInt k ) {
static WrappedInt& r = k;
return r.i++;
}
Here, we will see that once the temporary goes out of scope, and it explicitly zeroes out its value, when we reread it (with our dangling reference), we will get back 0:
int main()
{
int a = getID ( WrappedInt{10} ); // a == 10
int b = getID ( WrappedInt{10} ); // b == 0
std::cout << "a = " << a << ", b = " << b << std::endl;
return 0;
}
Related
maybe this question will be a bit complicated and maybe i'm missing something of stupid.
I'll try to explain without any source code, because my project is big and i don't know how/where to start.
I have:
bool result = false;
bool* pointer = &result;
these variables are stored in some classes.. (not as in the above code).
When result is created, his address is something like 0x28fddc.
and the pointer variable takes this address.
Suddendly, without any reason (maybe), his address is not 0x28fddc anymore but something like 0x3a8c6e4.
With the pointer variable, i am trying to change the result var by doing:
*result = true;
But obviously, this doesn't work (and it doesn't give me any error). It will not change result var because it's in another address.
I don't know why this happens.
Can you only tell me how could this happen? And i'll try to fix.
(This classes are everytime being updated in some functions with parameters passed by reference).
For example:
void update_class(obj_class &obj);
(These names are only an example).
I hope i've been clear and if not, i'll just delete this topic.
Sorry for bad english but i'm italian :)
EDIT:
Now i'll try to provide some code..
button.h
class button
{
public:
void check_tap(SDL_Event* e);
bool* done;
}
messagebox.h:
class messagebox
{
public:
messagebox();
bool result_ok;
button btn_ok;
}
void check_tap(std::vector<messagebox> &msgbox, SDL_Event* e) {
for(unsigned int k=0; k<msgbox.size(); k++) {
msgbox[k].btn_ok.check_tap(e);
// check_tap is a function that i create for checking if the user is tapping the button with his finger or not. When the user presses the button and leaves it the done variable should become true, but result_ok seems not to be affected because his address here is different. This problem is only in this case using messagebox. I created more other buttons outside and all works perfect.
}
}
messagebox.cpp:
messagebox::messagebox() {
// Initializing things
btn_ok.done = &result_ok;
// Here, btn_ok.done gets the address of result_ok..
}
main.cpp:
std::vector<messagebox> msgbox;
msgbox.push_back(msgbox());
No, the address of variables do not change during their lifetime.
However, storing the address of a variable is problematical if the variable ceases to exist. A simple example is
#include <iostream>
int *p;
void f()
{
int i;
p = &i;
}
int main();
{
f();
std::cout << (void *)p << '\n';
// other code here
f();
std::cout << (void *)p << '\n';
}
In the above case, the two values of p may be the same, or they may differ. This is not because the address of variables change. It is because a variable, i is created each time f() is called, and ceases to exist when f() returns. The variable i in the first call of f() is, as far as your program is concerned, a distinct variable from i during the second call of f().
Depending on what happens with "other code here" in the above, the memory occupied by i in the first call of f() may be inaccessible (e.g. used for another variable) during the second call of f() - so, during the second call of f(), i will have a different address than during the first. There are no guarantees - you may also get lucky (or unlucky depending on how you look at it) and the addresses printed will be the same.
If you are getting behaviour that suggests, to you, that the address of a variable is changing then - somewhere in your code - there is a bug of some form. Typically, this will involve storing the address of a variable in a pointer, and using (or accessing the value of) the pointer after the variable ceases to exist. And any dereferrencing of that pointer (e.g. to access the variable pointed at) has undefined behaviour.
For example, any usage of *p like
*p = 42;
or
std::cout << *p << '\n';
in the main() I have given above will give undefined behaviour.
The act of assigning a pointer to contain the address of that variable does not change the lifetime of that variable.
So, I am trying to use a variation of the approach from this question's answers to implement a large-ish, somewhat wide, constant tree structure in C++ (using VC++2012 with the v110 toolchain), as shown below:
#include <tuple>
#include <iostream>
struct test
{
test(const char* n, const test& n1, const test& n2):
name(n), nodes(n1, n2)
{
if (name)
std::cerr << "test() " << name << std::endl;
}
~test()
{
if (name)
std::cerr << "~test() " << name << std::endl;
}
const char* name;
std::tuple<const test&, const test&> nodes;
};
const test n = test(0, n, n);
test t = test("blah", test("bleh", n, n), n);
int main()
{
std::cerr << "get " << std::get<0>(t.nodes).name << std::endl;
return 0;
}
However, instead of outputting the expected
test() bleh
test() blah
get bleh
~test() bleh
~test() blah
or something of that ilk, I get
test() bleh
test() blah
~test() bleh
get
and then the program dies with a segfault (i.e. the Windows "this program has stopped working" box) when it tries to access the prematurely destroyed inner object. Is this my fault for assuming that making a temporary a const reference held subobject of another object would extend the lifetime in the same way a local or global named const reference would? Or is this a problem with VC++2012 not realizing that the temporary is being captured by reference in the parent object constructor when it should be doing so (i.e. not destroying the inner object until the outer object gets disposed of?)
This bit: std::get<0>(t.nodes).name is never going to work properly in your current code, whatever else is going on. That is because nodes contains references: std::tuple<const test&, const test&> instead of instances.
As a result when you pass the inner object: test("bleh", n, n), it is not copied into the nodes of the outer one. Therefore, when it goes out of scope and it is destroyed, your outer object's nodes (t.nodes) contains references pointing to the great beyond. As a result your program is going to take exception to that statement and crash with a segfault.
EDIT to add:
To clarify: the object that goes out of scope is the value of: test("bleh", n, n)
In this statement: test t = test("blah", test("bleh", n, n), n);
Because by the time t = test("blah",...) returns the inner object test("bleh",...) is gone. Note that t is actually a copy of the value of test("blah",...), the original temporary is also gone. (Well it gets more complex when you consider that the compiler may choose to optimise and do a move instead of a copy, but the semantics are as though it were a copy.)
I encounter some strange things in C++, but I don't know why?
I have a class like this
header file
class foo
{
public:
void call_foo();
int get_foo();
int get_foo(int val);
};
here is the cpp file
#include "foo.h"
#include <iostream>
using namespace std;
void foo::call_foo()
{
int i = 0;
int j = 33;
cout << i + j << endl;
cout << "Hello, Foo" << endl;
}
int foo::get_foo(int val)
{
int a = 345;
int rc = val + a;
cout << rc << endl;
return rc;
}
int foo::get_foo()
{
int a = 100;
int d = 23;
int rc = a + d;
cout << rc << endl;
return rc;
}
I using code to test as below
int main()
{
int* val = new int[100];
foo* foo_ptr;
foo_ptr = (foo*)val;
foo_ptr->call_foo();
foo_ptr->get_foo();
foo_ptr->get_foo(100);
delete [] val;
return 0;
}
then i compile and execute it.
clang++ foo.cpp main.cpp
Apple LLVM version 5.0 (clang-500.2.79)
os x 10.9
an int pointer convert to an object pointer, then call it's methods, it work! so weird!
Is there anybody know what is going on?
I wrote an article on my blog about why it works in my understood, Thanks all of you!! about object structure, virtual function table. just Chinese version :)
What you are experiencing is called Undefined Behavior.
Undefined Behavior means "anything can happen." Anything here includes the illusion that your code worked, did something you expected it to do, or didn't do something you expected it to do -- like crash.
Code that evokes Undefined Behavior is always faulty code. You cannot rely on Undefined Behavior, if simply for the reason that you cannot predict what will happen.
Now in this case, the reason why calling the methods might appear to work is because in practice an instance of a class doesn't get it's own copy of the code for each of the non-static methods. Instead, there's one copy of the code that is shared between all instances of foo. The pointer to that code never changes, so when you (incorrectly) resolve a pointer-to-foo and then call one of the methods through that pointer, the actual method you expected to call was actually called. This is all still Undefined Behavior however, and you need to fix your code.
It is undefined behaviour and your program is ill-formed. As far as language specification is concerned, anything could happen.
It just happens to appear to work because no member function access any data that would belong to a particular instance of foo objects. All they do is allocate local data and access cout.
It doesn't work, it has undefined behaviour.
However, the functions aren't virtual, and the object has no data members, so it's likely that your program won't actually touch the invalid memory, and so will have the same effect as calling the functions on a valid object.
Your class has no members and no virtual functions so when you call a member function through any arbitrary pointer it will 'work' since you have a statically bound function call and don't do any memory access that would be invalid. Bad things would happen if you tried to call a virtual function or access a member variable.
I'm having trouble understanding why this code works. I've been in the C# world for awhile and wanted to brush up on C/C++ before diving into the new stuff in C++11 like RValue Refs and move semantics.
I'm wondering why this code that I wrote works:
class InnerMember
{
private:
int _iValue;
public:
InnerMember(): _iValue(0) {};
InnerMember(int iValue) : _iValue (iValue) {};
int GetValue(void) { return _iValue; }
int SetValue(int iValue) { _iValue = iValue; }
};
class TestClass
{
private:
InnerMember _objValue;
public:
TestClass() : _objValue(1) {};
void SetValue(int iValue)
{
_objValue.SetValue(iValue);
}
InnerMember& GetRef(void)
{
return _objValue;
}
virtual ~TestClass() { std::cout << "I've been released!" << std::endl; }
};
int main (int argc, char *argv[])
{
TestClass* pobjTest = new TestClass();
std::cout << "Before:" << std::endl;
std::cout << pobjTest->GetRef().GetValue() << std::endl;
pobjTest->SetValue(5);
InnerMember& robjInner = pobjTest->GetRef();
delete pobjTest;
std::cout << "After:" << std::endl;
std::cout << robjInner.GetValue();
return 0;
}
The output is:
Before:
1
I've been released!
After:
5
Press any key to continue...
I thought that this would cause an error, since I access the referenced object InnerMember from TestClass after TestClass has been destroyed. Is there some sort of return value optimization going on? Or is it really returning a copy instead of passing back the reference?
I used GCC to with no optimizations (-O0) and it still ran without an issue.
I also used the -S switch to generate the assembly but my AMD64 knowledge is rusty and the name mangling didn't help.
That is undefined behaviour, which means even the "correct" behaviour could happen. When you delete something in C++, it is not erased from the memory, so accessing it before something else writes over it will sometimes maybe still work.
robjInner is still a reference to some deleted object in memory.
This would lead to undefined behaviour.
After deletion, the reference robjInner has been left dangling. You get back the previous value because no one else claimed that piece of memory yet.
Copied from here
A previously-valid reference only becomes invalid in two cases:
If it refers to an object with automatic allocation which goes out of scope,
If it refers to an object inside a block of dynamic memory which has been freed.
The first is easy to detect automatically if the reference has static scoping, but is still a problem if the reference is a member of a dynamically allocated object; the second is more difficult to assure. These are the only concern with references, and are suitably addressed by a reasonable allocation policy.
You can add a print statement inside InnerMember destructor to see what is going on. You will see InnerMember is destroyed after TestClass and the 5 you get is because no one write to that part of memory yet. But that reference is not valid anymore.
I am making a text-based RPG with C++ and I'm having the same error pop up time and again, and I'm sure I'm doing something fundamentally wrong, but I don't know what. Searches turned up the solution to the specific compiler error, but not anything I can use to fix the code I'm writing.
Question I want answered: How do I use pointers to enable communication of variables between separate functions? In other words, how can I use pointers to point to a variable's value so that I can use and manipulate that value in a function in which it was not declared?
TL;DR version: I'm trying to make my "exp" int variable communicate with outside functions using pointers. I get the error "ISO C++ forbids comparison between pointer and integer [-fpermissive]"
Long version: Here's a bit of the code where I'm having problems:
In file charlvl.cpp:
...
int lvl = 1;
int *exp = 0;//value I want communicated to main()
int str = 0;
int vit = 0;
...
in file fight.cpp (main.cpp):
...
//you've just killed a monster
cout << "\nThe monster drops to the ground." << endl;
cout << "You gained " << expValue << " experience!" << endl;
&exp += expValue;//&exp is the character's experience.
//expValue is the exp gained upon monster death
//*exp (from charlvl.cpp) is the value I want to communicate to here.
It was not declared here, but in charlvl.cpp. How do I establish communication between the declared variable in charlvl.cpp and main() without having to resort to using global variables?
If you defined exp as a global pointer, you don't need to think about the communication thing, you can just simply use it in different functions, but the way you use it is wrong.
&exp += expValue;
should be change to
*exp += expValue;
because * means get that pointer's content to me.
btw, try not defining exp as a pointer may also work.
int exp = 0;
exp += expValue;
This is all based on exp is a global var or global pointer.
if you have defined it in a function like this:
void func()
{
int *expPtr = 0;
int exp = 0
}
And you want to use it in another function
void use()
{
// trying to use expPtr or exp.
}
The ways I know is:
1, use a local var and return it in func(), but be aware that the returned var is only a copy.
int func()
{
int exp = 0;
exp++;
return exp;
}
2, use a local pointer and allocate memory for it, then return the pointer or assign the new memory to a global pointer. But be careful about the memory leak, you need to delete it as soon as you don't use it.
int * func()
{
int *expPtr = 0;
expPtr = new int(2);
return expPtr;
}
You've gotten the & and * operators confused. * turns an int* into an int, while & turns an int* into an int**.
This is what you want:
(*exp) += expValue;
You might want to consider using references.