Even though the following piece of code compiles and runs fine i want to know if it is a valid c++ code?
int main()
{
int *i= new int;
cout<<*i;
int &ref=*i;
cout<<ref;
delete &ref; //Especially is this statement valid?
return 0;
}
If it is valid then this must also be valid :
int& getInt() {
int* i = new int;
return *i; // OK?
}
int main(){
int& myInt = getInt(); // these two lines are same as shown in the example above ?
delete &myInt; //is this OK too?
}
It's correct code and it will work on all platforms and compilers.
However, it's probably not best practice as the reference is usually used when the called party retains the ownership of the object.
Related
This is my code, after a = b; in the function, a is still nullptr....
int getBox(int *a) {
int *b = new int;
*b = 3;
a = b;
std::cout << *a;
}
int main() {
int *a = nullptr;
getBox(a);
std::cout << a;
}
I guess it's a very simple problem... Maybe I forgot too much about C++
I'm not sure what you're trying to do, but this row inside the getBox():
a=&b;
Doesn't actually change a in the main, you actually overrides the pointer(the copy that was made by the function), and make it point somewhere else.
You can do something like this(again, I don't see the point) :
int getBox(int ** a){
int *b = new int;
*b=3;
*a=b;
std::cout<<*a;
}
int main(){
int *a= nullptr;
getBox(&a);
std::cout<<a;
}
Let's assume there is some type T. Now here are 3 different kinds of functions:
void f(T a) { // pass by value (this is a copy of the 'a' in main)
a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(a);
// a is still something
}
void f(T &a) { // pass by reference (this is a reference to the 'a' in main)
a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(a);
// a is now something else
}
void f(T *a) { // pass by address (this is a pointer to the address the 'a' in main)
*a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(&a);
// a is now something else
}
Now you can apply this logic to any T you want, such as int, or int*, and the same rules will work. You can try this out with getBox and see the effect of each version, which should help you understand what's going on. Note that you are using the first version (pass by value), but for the result you are expecting, you should use the second version (pass by reference).
If you really want to change what a is pointing to, then you can think it this way maybe it will help to make it a bit easier to understand. A is an int pointer and the function getBox takes a reference that you can modify its value which is an int pointer.
void getBox(int* &a) {
int *b = new int;
*b = 3;
a = b;
std::cout << *a;
}
int main(){
int *a= nullptr;
getBox(a);
std::cout<< *a;
}
This will change the value of a, which is a new pointer value to b.
Yes of course, why should changing a in getBox change the value of a in main? If you think the answer is 'because it's a pointer' then I'm afraid you've misunderstood pointers.
Look at this code
int getBox(int a){
a=3;
std::cout<<a;
}
int main(){
int a= 0;
getBox(a);
std::cout<<a;
}
Setting a=3 in getBox has no effect on a in main. Your code is exactly the same, but for some reason because pointers are involved beginners often think it works differently. It doesn't.
You can however use pointers in this way to change what is being pointed at, that's the important thing, but changing the pointer itself doesn't work in the way you are expecting.
You probably only want to change to getBox(int * & a). You then pass a reference to the pointer a to the function instead of creating a copy of the pointer that points to the same address in your case NULL.
[Global Scope]
myClass *objA, *objB, *obj;
int objnum;
I want to switch between objA and objB and assign them alternatively to obj, so in main() I have:
int main()
{
objA = new myClass(parameters...);
objB = new myClass(parameters...);
// start with objA;
objnum = 0;
obj = objA;
}
At some point a function is called that switches between the two objects:
void switchObjects()
{
if (++objnum > 1) objnum = 0;
obj = objnum == 0 ? objA : objB;
}
And in the function where I use the object, I have:
void doYourJob()
{
int res = obj->work();
}
Now the weird thing is that if I don't assign obj to either objA or objB, it still works. I would expect an exception, instead. Even if I do obj = NULL;, it still works! What's this voodoo?
OK, I could provide a different example that brings to the same result, without using a NULL pointer:
myClass *obj[2];
int objnum;
void switchObject()
{
if (++objnum > 1) objnum = 0;
}
void doYourJob()
{
res = obj[objnum]->work();
}
int main()
{
obj[0] = new myClass(parameters...);
obj[1] = new myClass(parameters...);
objnum = 0;
}
With the above code, regardless of the value of objnum, I still get both objects working together, even if I'm calling work() on only one instance.
And if I replace the function doYourJob() with this:
void doYourJob()
{
int res1 = obj[0]->work();
int res2 = obj[1]->work();
}
I always get the results doubled, as if I were calling the function work() twice on every object.
Consider a simpler example:
#include <iostream>
struct X
{
void foo() { std::cout << "Works" << std::endl; }
};
int main() {
X* x = nullptr;
x->foo();
}
With most compilers and on most platforms, this code will appear to work fine, despite having called foo on a null pointer. However, the behaviour is technically undefined. That is, the C++ language gives no restrictions about what might happen if you do this.
Why does it work? Well, calling a member function only requires knowing the type of the object it is being called on. We know that x points at an X, so we know what function to call: X::foo. In many cases, it may be difficult or even impossible to know if a pointer points at a real object, so the compiler just lets it happen. The body of the function, in this case, doesn't actually depend on the X object actually existing, so it just works. This isn't something you can depend on though.
This question already has answers here:
Returning a reference to a local variable in C++
(3 answers)
Closed 8 years ago.
I'm trying to understand why the second piece of code compiles fine, given that the first doesn't.
int & test(void) {
int v = 0;
return v;
}
int main(void){
int & r = test();
return 0;
}
I understand that this doesn't work because you can't pass a reference to an automatic variable that will be deleted. It seems to me that the code below should have the same problem but it doesn't.
int & test1(int & x) {
return x;
}
int & test2(void) {
int x = 0;
return test1(x);
}
int main(void){
int & r = test2();
return 0;
}
Seems like the intermediate function is solving the problem. But why?
Just because something compiles, doesn't mean it works...
The two "alternatives" both suffer from the same exact problem; r, in main, is a dangling reference, what it refers to is long gone, and using it will lead to undefined behavior.
1st snippet
In the first example it's easy enough for the compiler to see that you are returning a reference to a local variable, which (as compilers know) doesn't make any sense.. the referred to instance will be dead when the reference reach main.
The compiler is being a good champ and tells you about the issue.
2nd snippet
In the second example you are doing the same thing, but adding a redirection in-between. A compiler got many tricks up its sleeve, but back-tracing every possible execution path to see if a developer is returning a reference to a local variable, by indirection, isn't one of them.
The compiler can't see that you are being bad, and it cannot warn you about issues it doesn't know about.
Conclusion
Returning a reference to a local variable is bad, no matter how you do it.
Think about what the compiler would have to do to catch the problem you're demonstrating. It would have to look at all callers of test1 to see whether they're passing it a local. Perhaps easy enough, but what if you insert more and more intermediate functions?
int & test1(int & x) {
return x;
}
int & test2(int & x) {
return test1(x);
}
int & test3() {
int x = 0;
return test2(x);
}
int main(void){
int & r = test3();
return r;
}
The compiler would have to look not only at all callers of test1, but then also all callers of test2. It would also have to work through test2 (imagine that it's more complex than the example here) to see whether it's passing any of its own locals to test1. Extrapolate that to a truly complex piece of code--keeping track of that sort of thing would be prohibitively complex. The compiler can only do so much to protect us from ourselves.
The both code examples are ill-formed and have undefined behaviour because local objects will be deleted after exiting the functions. So the references will be invalid.
To understand that the second example does not differ from the first example you could rewrite it the following way (insetad of calling the second function)
/*
int & test1(int & x) {
return x;
}
*/
int & test2(void) {
int x = 0;
/* return test1(x);*/
int &r = x;
return r;
}
As you see there is no any difference between the examples.
To achieve what you want you could the following way
int test()
{
int v = 0;
return v;
}
int main()
{
const int & r = test();
return 0;
}
Can anyone tell me whether this is safe and defined:
class RefClass
{
public:
RefClass(int i) { this->i = i; }
int& GetRef() { return i; }
private:
int i;
};
RefClass rc(10);
int* refp;
{
refp = &rc.GetRef();
}
*refp = 20;
Specifically I am concerned with the lifetime of the returned reference in the nested scope and whether it can be referenced in that scope and then later dereferenced as an lvalue after that scope has dissolved.
This code compiles and runs as expected in VS2012, but that doesn't mean it will in the next version, so I am trying to find a definitive answer.
Yes, that's fine.
The returned reference is a temporary, lasting until the end of the statement containing the function call. It's used within its lifetime to set refp to point to its target, rc.i. It's not needed to dereference the pointer after that.
The only danger is if the object might be destroyed, leaving the pointer dangling:
int* refp;
{
RefClass rc(10);
refp = &rc.GetRef();
} // rc is destroyed here
*refp = 20; // BOOM!!!
Yep, this is all right. You'd have issues in the following case:
int* refp;
{
RefClass rc(10);
refp = &rc.GetRef();
}
*refp = 20;
While trying to find out a problem that occurs only in a release build and not in the debug build I noticed the following behaviour (String would be invalid and would not point to anything while the int would be fine). I have given code below which gives an idea of what I was going through
typedef boost::shared_ptr<MyClass> shared_cls
typedef std::deque<shared_cls> vector_def;
typedef boost::shared_ptr<vector_def> shared_vector_def;
typedef boost::unordered_map<int,shared_vector_def> inner_map_def;
typedef boost::shared_ptr<inner_map_def> shared_inner_map_def;
static boost::unordered_map<std::string,shared_inner_map_def> bcontainer;
shared_cls& SomeMethod(const std::string& symb,const int& no)
{
shared_inner_map_def tshare = bcontainer[symb];
shared_vector_def tmp = tshare->at(no);
shared_cls t = tmp->back();
return t
}
The object MyClass looks like this
class SomeClass
{
private:
int i;
std::string s;
void set_i(int rx)
{
i = rx;
}
int get_i()
{
return i;
}
void set_s(std::string rx)
{
s = rx;
}
std::string get_s()
{
return s;
}
}
Now when I use the above method as in the following code
void main()
{
shared_cls r = SomeMethod("IBM",12);
//Here r does not have a valid string s
//However it does have a valid int i
}
Now my question is in the above main when I call the SomeMethod the r returned does not have a valid string s. It has a scrambled value I found this out by using a logger. However the value of s is totally find during the function SomeMethod. I resolved this issue by not returning the shared pointer by reference.In that case it works. Why does removing the reference make it work
Your shared_cls t goes out of scope because it is defined in the function SomeMethod itself. You need to return shared pointers by value if they are defined in the scope. In the link, it is explained why it is dangerous to return the reference of a temporary object.
In the case of std::string, string has a reference counting mechanism and when it's reference is decremented to zero, it becomes invalidated and a segmentation fault may be observed in such a case. Even if member int i is returned properly, it is still undefined behavior.