Passing a pointer to temporary object - c++

We know that we can pass temporary objects to functions by const reference, like this:
class A
{
public:
A(int _b = 0)
{
b = _b;
}
int b;
};
void foo(A& a) {printf("%d", a.b);}
void cfoo(const A& a) {printf("%d", a.b);}
int main(void)
{
//foo(A(4)); doesn't compile
cfoo(A(5));
}
but what about passing by pointer?
why does this compile?
void pfoo(A* pa) {pa->b = 19;}
int main(void)
{
pfoo(&A(5));
}

but what about passing anonymous variables pointer? why does this compile?
You are probably using a compiler that does not honour C++ standard.
No address of an r-value (temporary) object can be taken. That should not compile.
However, operator& can be overloaded, so that it can be invoked on a temporary object, e.g.:
struct A
{
A* operator&() { return this; }
};
In C++11 a temporary object can be bound to an r-value reference. After that r-value reference behaves like an l-value and hence the address of a temporary object can be taken:
struct A {};
void foo(A*);
void foo(A&& a) { foo(&a); }
int main() {
foo(A{});
}

Related

C++ template member function having pointer reference template parameter

class BI {
public:
virtual void fun() = 0;
virtual ~BI() {}
};
class B : public BI {
public:
void fun() {}
};
template <typename T>
class A {
T* obj;
public:
void funT(const T*&) /* adding reference is creating error */;
};
template <typename T>
void A<T>::funT(const T*& obj) {
}
int main() {
A<B> obj;
obj.funT(new B());
}
when compiling the above code with g++ compiler, I am getting the error: no matching function for call to A::funT(B)*. But when I remove the reference '&' operator from the funT() declaration as void funT(const T* obj), then it compiles and works fine. Why the reference operator is not allowed here?
You're asking for a reference to a pointer, you can't get references (unless they're C++11 rvalue references) to temporary values.
Make sure you have a lvalue passed as parameter to have the reference working.
e.g.
#include <iostream>
using namespace std;
class BI {
public:
virtual void fun() = 0;
virtual ~BI() {}
};
class B : public BI {
public:
void fun() {}
};
template <typename T>
class A {
T* obj;
public:
void funT(const T*&);
};
template <typename T>
void A<T>::funT(const T*& obj) {
}
int main() {
A<B> obj;
const B* ptr = new B(); // <-- This is an lvalue
obj.funT(ptr);
delete ptr; // Also clean it up after you used it
}
http://ideone.com/T4QJzi
Here is a more simple program which exhibits the same problem:
void fun(const int*&) {}
int main() {
int x;
fun(&x);
}
It yields the following error:
invalid initialization of non-const reference of type ‘const int*&’
from an rvalue of type ‘int*’
That makes sense. fun takes an argument of type "reference to non-const pointer to const int", and we tried to pass it a temporary of type "pointer to int". References to non-const types don't bind to temporaries, because temporaries are usually immutable. In this case, if we were allowed to pass &x as the argument to fun, then fun would be able to modify the address of x, which doesn't make any sense.
As you noticed, removing the & makes the code well formed:
void fun(const int*) {}
Now we are simply passing a pointer to int where a value of type pointer to const int is expected, which is a simple implicit conversion.
Alternatively, you might have intended for fun to take an argument of type "reference to const pointer to int":
void fun(int* const&) {}
Or a reference to const pointer to const int:
void fun(const int* const&) {}
But a reference to a const pointer is kind of silly, as a simple pointer would be just as good.
Finally, you could keep your original declaration of fun, and just avoid trying to pass a temporary as its argument.
The error msg is clear. Parameter type is of reference to pointer to T, but you are sending pointer to T. Temporaries cannot be passed as reference in this case. You can write:
int main() {
A<B> obj;
const B* b=new B(); //create a lvalue
obj.funT(b);
delete b; // make sure to release memory.
}

C++ temporary object's lifetime

void foo(const C &);
foo(C());
In this case, temporary C object lives until the end of foo().
But my question is:
struct C { operator int(); }
void bar(int i);
bar(C());
In that case, Does temporary C object live until the end of bar()? If not, Is there any way to make temporary object live until the end of bar()?
edit: Thanks to user2109558, I know the code doesn't work. Then does the following code work well?
void bar(int i);
void bar(C &&c) { bar(c); }
No!the codebar(C());
is equal to
int num = C();
bar(num);
So , temporary C object does not live until the end of bar()
you have to change bar function parameter.such as void bar(const C &) or add global C object variable eg:
C c;
void bar(int i) {
.....
}
but no suggestion do it.

Union of const/non-const Object Pointers

Consider the sample code below:
class A
{
public:
A() : n(0) {}
int n;
};
class B
{
public:
B(A* a) : mA(a) { }
B(const A* a) : mConstA(a) { }
union {
A* mA;
const A* mConstA;
};
};
int main()
{
A a;
B b1(&a);
B b2(const_cast<const A*>(&a));
return 0;
}
At construction, b1 would have a mutable pointer to a, while b2 would have an immutable pointer to a. In this scenario, b1.mA equals b2.mConstA, and b1.mConstA equals b2.mA.
Are these equalities always true when you have a union of const and non-const object pointers?
Similarly, the code below compiles/runs fine:
int main()
{
const A a;
B b(&a);
b.mA->n = 3; // Blasphemy!!!
return 0;
}
But is it guaranteed for b.mA to always be equal to b.mConstA?
Are these equalities always true when you have a union of const and non-const members?
Yes, both pointers will refer to the same object in the same address. The bits in memory will be the same.
But is it guaranteed for b.mA to always be equal to b.mConstA?
Yes, their values will be the same, but that does not mean that you can really use it. This is equivalent to using const_cast, you will get a non-const pointer to the object, but if the object is really const, using that pointer to modify the object is undefined behavior.

C++ polymorphism with boost scoped_ptr

Why does the following code not allow foo(ptr) to be called ?
#include <boost/scoped_ptr.hpp>
struct A {
virtual ~A() {}
};
struct B: public A {};
void foo(boost::scoped_ptr<A>& a) {}
void goo(A& a) {}
int main() {
boost::scoped_ptr<B> ptr(new B);
foo(ptr);
B b;
goo(b);
}
The corresponding form where we pass references works as expected. Are we supposed not to do polymorphism
with boost scoped_ptr ?
g++ with boost 1.49 gives me:
error: invalid initialization of reference of type ‘boost::scoped_ptr<A>&’ from expression of type ‘boost::scoped_ptr<B>’
That's because foo, for some reason, takes a scoped pointer by reference. That is completely unnecessary and is the reason why the call fails. There is a conversion from scoped_ptr<B> to scoped_ptr<A> but not from scoped_ptr<B>& to scoped_ptr<A>&.
You should pass it as reference to const.
void foo(boost::scoped_ptr<A> const & a) {}
Incidentally, this isn't a "problem" of smart pointers per se. The following code fails for the same reasons as yours.
void foo(A*& p) {}
int main()
{
B* p = new B;
foo(p); //FAIL
}
In order to fix this you have to pass the pointer either by value, or, if you're sufficiently perverted, by reference to const
void foo (A * const & p); // <-- a perv wrote this

Is this valid C++ code according to standard?

I have this sample code:
struct A
{
bool test() const
{
return false;
}
};
template <typename T = A>
class Test
{
public:
Test(const T& t = T()) : t_(t){}
void f()
{
if(t_.test())
{
//Do something
}
}
private:
const T& t_;
};
int main()
{
Test<> a;
a.f();
}
Basically I am worried about the constructor of Test where I am storing a const reference to a temporary variable and using it in methof f. Will the temporary object reference remains valid inside f ?
It won't remain valid. The temporary object will be destroyed after initializing a. At the time you call f you invoke undefined behavior by calling test. Only the following is valid:
// Valid - both temporary objects are alive until after the
// full expression has been evaluated.
Test<>().f();