Here's some C++ code:
#include <iostream>
class A
{
int x;
int y;
double v;
public:
A(int x, int y)
:x(x),y(y)
{
std::cerr << "A("<<x<<","<<y<<")\n";
}
~A()
{
std::cerr << "~A()\n";
}
operator double* ()
{
v=1.5*x+y;
return &v;
}
};
void f(double* val)
{
std::cerr << "f("<<*val<<")\n";
*val=0.3;
}
int main()
{
f(A(3,5));
}
I get the following as output:
A(3,5)
f(9.5)
~A()
I.e. as I'd like it to work. But I'm not sure whether destructor of A must be called after f returns. Is it guaranteed? Can the pointer returned by operator double* () somehow become invalid in the call of f?
You are declaring an A object as an actual parameter of f, when you do that, for all effects the new object is like a local variable of f so ~A is guaranteed to be called at the end of f execution.
If f returns the address returned by operator double* () and it is used after f has returned you will be accessing to invalid memory. One way to avoid this situation is making double v static but you have to consider that, in your code, the A class created object only exits while f block is running.
The arguments to a function are evaluated before the function is invoked, and the temporaries will live to the end of the full expression that they are in. So yes, the instance of A will live to just past the end of the invocation of f.
Related
I have this:
struct Point
{
size_t x;
size_t y;
~Point()
{
std::cout << "Destro" << "\n";
}
};
const Point& getPoint()
{
return { 100, 120 };
}
int main()
{
Point p = getPoint();
std::cout << "Exit" << "\n";
}
and the result is
Destro
Exit
Destro
I'm basically trying to make the getPoint method not have to copy the Point class.
Here is what's happening so far:
Point Created
Point copied to the result
Point destroyed
How can I make it so that Point is only destroyed once?
You need to return by value instead of reference. Using
Point getPoint()
{
return { 100, 120 };
}
Allows C++17's guaranteed copy elision to kick in which causes Point p = getPoint(); to act as if it was Point p{ 100, 120 };
Side note: Never, Never, Never, return a function local object by reference. That object will be destroyed at the end of the function leaving you with a dangling reference and using that is undefined behavior.
Here's an example of what it looks like you're trying to achieve...
#include <iostream>
struct Point {
size_t x;
size_t y;
~Point() { std::cout << "Destructor called\n"; }
// Explicitly deleting the Copy Constructor only to illustrate a point.
Point(const Point& other) = delete;
};
const Point makePoint(size_t a, size_t b) {
return Point{ a, b };
}
int main() {
Point a = makePoint(3, 5);
std::cout << a.x << ',' << a.y << '\n';
}
Output:
3,5
Destructor called
If you noticed, I explicitly deleted the Copy Constructor and left the Assignment Operator undeclared so that it will use the default. The struct is still using the default constructor and I didn't define a User Defined constructor.
In makePoint() I added two parameters/arguments to the function so that the user can set any values to the Point object. The function is returning a const Type object. The return statement in the function is using:
return Point{a, b};
instead of
return Point(a, b);
The latter will fail to compile because there is no user-defined constructor. However, the former works because I'm using brace-initialization. This will allow construction of the object on return instead of creating a temporary on the stack frame of the function and copying that temporary as its return value. This is a form of Copy Elision.
Now, if you want to be able to copy this object, you can remove the deleted constructor and allow the class to use its default copy constructor. The semantics of the Copy Elision will still work.
This will have the same exact results. I showed the explicit deletion of the Copy Constructor to initially prevent any Copying semantics. Then explained how the code works so you can take the original above and remove the line for the deleted copy constructor and it will still work the same:
struct Point {
size_t x;
size_t y;
~Point() { std::cout << "Destructor called\n"; }
};
const Point makePoint(size_t a, size_t b) {
return Point{ a, b };
}
The functionality or behind the scenes magic is happening within the function makePoint() and that it returns a const object and uses brace-initialization of the class.
If i have an instance of std::function that is bound to a member function of an object instance and that object instance goes out of scope and is otherwise destroyed will my std::function object now be considered to be a bad pointer that will fail if called?
Example:
int main(int argc,const char* argv){
type* instance = new type();
std::function<foo(bar)> func = std::bind(type::func,instance);
delete instance;
func(0);//is this an invalid call
}
Is there something in the standard that specifies what should happen? My hunch is that it will throw and exception because the object no longer exists
EDIT:
Does the standard specify what should happen?
Is it undefined behavior?
EDIT 2:
#include <iostream>
#include <functional>
class foo{
public:
void bar(int i){
std::cout<<i<<std::endl;
}
};
int main(int argc, const char * argv[]) {
foo* bar = new foo();
std::function<void(int)> f = std::bind(&foo::bar, bar,std::placeholders::_1);
delete bar;
f(0);//calling the dead objects function? Shouldn't this throw an exception?
return 0;
}
Running this code i receive an output value of 0;
What will happen is undefined behavior.
The bind() call will return some object that contains a copy of instance, so that when you call func(0) will effectively call:
(instance->*(&type::func))(0);
Dereferencing an invalid pointer, as you would do there if instance were deleted, is undefined behavior. It will not throw an exception (although, it's undefined, so it could, who knows).
Note that you're missing a placeholder in your call:
std::function<foo(bar)> func =
std::bind(type::func, instance, std::placeholders::_1);
// ^^^^^^^ here ^^^^^^^^^
Without that, you can't call func(0) even with a non-deleted instance.
Updating your example code to better illustrate what's going on:
struct foo{
int f;
~foo() { f = 0; }
void bar(int i) {
std::cout << i+f << std::endl;
}
};
With that added destructor, you can see the difference between copying the pointer (in f) and copying the object that was pointed to (in g):
foo* bar = new foo{42};
std::function<void(int)> f = std::bind(&foo::bar, bar, std::placeholders::_1);
std::function<void(int)> g = std::bind(&foo::bar, *bar, std::placeholders::_1);
f(100); // prints 142
g(100); // prints 142
delete bar;
f(100); // prints 100
g(100); // prints 142 still, because it has a copy of
// the object bar pointed to, rather than a copy
// of the pointer
I was studying how a function returns an object by means of return-by-value. So, to test the theory, I ran a simple program that had a function returning an instance of myclass - a custom-made class.
#include <iostream>
#include <cstdio>
using namespace std;
class myclass {
int i;
public:
void set_i(int n) { i=n; }
~myclass();
};
myclass f(int k); // return object of type myclass
int main()
{
f(20);
return 0;
}
myclass f(int k)
{
myclass x;
x.set_i(k);
return x;
}
myclass::~myclass() {
cout << "hello\n";
}
I overloaded the destructor by placing a cout "hello" statement in it so that I would be able to track when the object's local copy within the function as well as the temporary object created during execution of the return statement were destroyed.
So, I was expected 2 calls to the destructor; one for the function's local copy of the object and one for the temporary object. But instead, I received only one!
Please share why my program did not output "hello" twice.
Thanks.
That is an effect of return value optimization which eliminates the temporary object created to hold a function's return value. This optimizes out the redundant copy constructor and destructor calls.
I've been messing about with member-function pointers in relation to a previous question. In the code below I call methods on a class (B) that change a variable (count) in it, but I never make an instance of this class. Why does this work?
#include <iostream>
#include <string>
#include <map>
class A;
typedef int (A::*MEMFUNC)(int, int);
#define HANDLER(aclass, aproc) (MEMFUNC)(&aclass::aproc)
enum
{
ADD=1,
MUL,
SUB,
DIV
};
class B
{
int count;
public:
B() : count(0) {}
~B() {}
int multiply(int x, int y) { count++; return x*y*count; }
int divide(int x, int y) { count++; if (y!=0) return (x/y)*count; else return 0; }
};
class A
{
std::map< int, MEMFUNC > funcs;
public:
A() { AddLocals(); }
~A() {}
int CallLocal(int nID, int x, int y)
{
MEMFUNC f = funcs[nID];
if (f) return (this->*f)(x, y);
else return 0;
}
void AddLocals()
{
Add(ADD, HANDLER(A, plus));
Add(MUL, HANDLER(B, multiply));
Add(SUB, HANDLER(A, subtract));
Add(DIV, HANDLER(B, divide));
}
void Add(int nID, MEMFUNC f) { funcs[nID] = f; }
int plus(int x, int y) { return x+y; }
int subtract(int x, int y) { return x-y; }
};
int main()
{
A aA;
int a,b,c,d;
a = aA.CallLocal(ADD,8,2);
b = aA.CallLocal(MUL,8,2);
c = aA.CallLocal(SUB,8,2);
d = aA.CallLocal(DIV,8,2);
std::cout << "a = " << a << "\n"
<< "b = " << b << "\n"
<< "c = " << c << "\n"
<< "d = " << d << "\n";
return 0;
}
(sorry, me again, but this member-function pointers are making me itch)
Your cast in the HANDLER macro def tells the compiler "Shut up! I know what I'm doing!".
So the compiler shuts up.
You still have Undefined Behavior, but one property of UB is that in some cases it does what you'd naïvely expect, or what you'd want it to do.
But don't be surprised if such code crashes, or causes crashes or mysterious incorrect result in apparently totally unrelated code.
Or, for example, causes nasal demons to fly out your nose.
Cheers & hth.
The result is just undefined behavior. For example, I get that b = 2083899728 and d = -552766888.
The persistent thing you are manipulating is most likely an int's worth of bytes in the map instance of A (because if the object were indeed a B, then that's the offset where the count member would be located.
In my stdlib implementation, the first member of map is the comparison function, in this case an instance of std::less<int>. Its size is 1, but there must be unused padding bytes after that to align the other members of map. That is, (at least) the first four bytes of this instantiation of std::map contains just garbage that is not used for anything (std::less doesn't have data members and doesn't store state, it just takes space in the map). That would explain why the code doesn't crash - it is modifying a part of the map instance which doesn't affect the functioning of the map.
Add more data members in B before count, and now count++ will affect crucial parts of the map's internal representation and you can get a crash.
C-casting lets you get away with all sorts of horrid behaviour but doesn't mean it's ok to do it so simply don't.
Get rid of your macro completely and do not cast. You can probably use boost::function and boost::bind to get the behaviour you actually want.
Your code is invoking undefined behaviour by trying to call a member of class B using an object of class A.
We can try to explain how the compiler can come to the behaviour you have observed, but there is no guarantee that you will get the same behaviour if you change anything (add/remove a member, change compiler settings or use a different compiler).
With the cast in the HANDLER macro, you are telling the compiler not to warn you about the use of incompatible types but just to do as you tell it to. In this case, you tell the compiler to reinterpret the address of a member of any class as being the address of a member of class A.
When you later try to call, for example, B::multiply, that function does not know that it is not working on an object of class B, so it will happily clobber the bytes of aA that would correspond to the B::count member if it had been a B object. Most likely, these bytes are actually being used by A::funcs, but apparently not for anything critical. If you change class A to:
class A
{
int count;
std::map< int, MEMFUNC > funcs;
public:
A() : count(0) { AddLocals(); }
~A() {}
int CallLocal(int nID, int x, int y)
{
MEMFUNC f = funcs[nID];
if (f) return (this->*f)(x, y);
else return 0;
}
int Count()
{
return count;
}
void AddLocals()
{
Add(ADD, HANDLER(A, plus));
Add(MUL, HANDLER(B, multiply));
Add(SUB, HANDLER(A, subtract));
Add(DIV, HANDLER(B, divide));
}
void Add(int nID, MEMFUNC f) { funcs[nID] = f; }
int plus(int x, int y) { return x+y; }
int subtract(int x, int y) { return x-y; }
};
then printing the result of aA.Count() at various places might show the effect.
The compiler is calling the expected function, because they are non-virtual member functions.
The only difference between non-member functions and non-virtual member functions is in the hidden argument that feeds the this pointer in a member function. So, if you take the address of a non-virtual member function, you will get a fixed address that is distinct for every function.
If the member functions had been virtual, then the compiler would, most likely, have returned the index into the v-table as a pointer for that function (together with some kind of indication that it is a v-table offset). Then the code can determine at the call-site if it can do a direct call to the member function or if it needs to do an indirect call through the v-table of the object the function is called on.
There are several duplicates of this but nobody explains why I can use a member variable to store the pointer (in FOO) but when I try it with a local variable (in the commented portion of BAR), it's illegal. Could anybody explain this?
#include <iostream>
using namespace std;
class FOO
{
public:
int (FOO::*fptr)(int a, int b);
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
fptr = &FOO::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
};
class BAR
{
public:
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
//int (BAR::*fptr)(int a, int b);
//fptr = &BAR::add_stuff;
//cout<<(*fptr)(a,b)<<endl;
}
};
int main()
{
FOO test;
test.call_adder(10,20);
return 0;
}
Apparently, you misunderstand the meaning of this->* in the call in FOO.
When you use this->* with the member fptr pointer, the this->* part has absolutely nothing to do with fptr being a member of FOO. When you call a member function using a pointer-to-member, you have to use the ->* operator (or .* operator) and you always have to specify the actual object you want to use with that pointer-to-member. This is what the this->* portion of the calling expression does. I.e. the call will always look as
(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)
or as
(<object> .* <pointer-to-member>) (<arguments>)
The left-hand side of the call (<pointer-to-object> or <object> above) cannot be omitted.
In other words, it doesn't matter whether fptr is a member variable, local variable, global variable or any other kind of variable, the call through fptr will always look as
(this->*fptr)(a, b);
assuming that you want to invoke it with *this object. If, for another example, you want to invoke it for some other object pointed by pointer pfoo, the call will look as follows
FOO *pfoo;
...
(pfoo->*fptr)(a, b);
In your BAR class the call should look as (this->*fptr)(a,b) even though fptr is a local variable.
When you use a member function pointer, you need to specify the object on which it is acting.
I.e. you need to create a pointer to an instance of BAR (let's call it bar) and do:
(bar->*fptr)(a,b)
to call the function, or an instance of BAR and do:
(bar.*fptr)(a,b)
Put another way:
#include <iostream>
class BAR
{
int i;
public:
BAR(): i(0) {};
int AddOne() { return ++i; };
int GetI() { return i; };
}
int main()
{
BAR bar;
auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
std::cout << (bar.*fPtr)(); //This will print 1 to the console
std::cout << std::endl;
std::cout << bar.GetI(); //This will also print 1 to the console.
}
I don't think the usage of the variable itself is illegal. What's illegal is trying to call that method without a class instance.
That is, you should really call (someVar->*fptr)(a,b) where someVar is of type BAR*
BAR::call_adder() had a couple of problems. For one, you were mixing case. In C++, case is signifigant. BAR and bar are not the same. Second, you decalred and assigned the pointer fine, after fixing the case problems, but when you try to call through the pointer to a member function, you need to use operator ->* with a class object. Here's is call_adder() fixed
void call_adder(int a, int b)
{
int (BAR::*fptr)(int a, int b);
fptr = &BAR::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
When you invoke a member function of a class the compiler generates code to set 'this' while the function runs. When you call it from a function pointer that isn't done. There are ways to get around it but they aren't 'guaranteed' to work and are compiler dependent. You can do it as long as you're careful and know the possible problems you can run into.