In the following code:
#include <iostream>
class Foo{
public:
int *a, *b;
}
Foo::Foo(int x, int y) : a( new int ( x ) ) , b( new int ( y ) )
{
}
Foo test(1,2);
If I want to cout the derefereced value stored in pointer variable a, why do I write:
std::cout << *test.a << std::endl; //method 1
and not:
std::cout << test.(*a) << std::endl; //method 2
It would seem to me that we are accessing the dereferenced value of a i.e. *a, and this is a member variable of the test object of class Foo so method 2 feels more syntactically correct. Method 1 (the correct way I believe) appears to dereference the whole test object.
The reason you need *test.a instead of test.(*a) is because a itself does't exist (from a variable in scope perspective). It's a member of Foo so to access Foo::a you need test.a. Then you apply * to test.a since test.a is a pointer.
Related
My question is different from Static variables in member functions.
class A {
public:
void foo() {
B b(params_); // It takes lots of time to construct b. b is only used in foo().
// do something with b
return;
}
private:
int params_;
};
int main() {
A a1(params1), a2(params2);
a1.foo(); // call 1
a1.foo(); // call 2
a2.foo(); // call 3
}
I want b to be same in call 1 & call 2 and constructed only once and should be seen in foo() only. However b should have different value in call 2 & call 3 due to different value of params_ in a1 and a2. How should I declare b?
static variable in foo(): b has same value across different instances a1, a2. It doesn't meet my requirement.
local variable in foo(): b is constructed every time foo() is called. It doesn't meet my requirement.
member variable of class A: b can be seen by other member functions of A. It doesn't meet my requirement.
other good choice?
You can try this, but I think that it's an ugly trick:
#include <iostream>
#include <map>
#include <memory>
class B {
public:
B(int src) {
std::cout << "B constructed from " << src << "." << std::endl ;
}
void foo(int i) {
std::cout << "B.foo(" << i << ") called." << std::endl ;
}
} ;
class A {
public:
int inst ;
A(int v) : inst(v) {}
void foo() {
// Static map associating current A instance and a B object.
static std::map<A*,std::unique_ptr<B>> Bmap ;
// Search an already existing instance.
auto b = Bmap.find(this) ;
if (b==Bmap.end())
// Not found, create one.
b = Bmap.insert({this,std::make_unique<B>(B(inst))}).first ;
// If already an instance of B, returns it, otherwise create it with params_
// Do something with b.
b->second->foo(inst) ;
return;
}
} ;
int main() {
A a1(1), a2(2) ;
a1.foo() ;
a2.foo() ;
a1.foo() ;
}
This code compiles and run, it produces that output:
B constructed from 1.
B.foo(1) called.
B constructed from 2.
B.foo(2) called.
B.foo(1) called.
But a member variable would be cleaner and better, even if you use just-in-time initialization and leaves it to nullptr until you really need it.
I am learning C++ so maybe my question is dumb. I am creating a function that takes a lambda as a parameter. I just want to know if its safe to call it when the lambda function goes out of scope. With code is easier to explain what I mean:
struct SomeStruct
{
// store pointer to callback function
void (*callback)(bool);
int arg1;
int arg2;
};
void some_method(int arg1, int arg2, void (*on_complete_callback)(bool))
{
SomeStruct s;
s.callback = on_complete_callback;
s.arg1 = arg1;
s.arg2 = arg2;
// this helper class will copy the struct even though it is passed by reference
SomeHelperClass->SomeQueue.enqueue( &s );
// do work on a separate task/thread
SomeHelperClass->CreateThread([](){
// get copy of struct
SomeStruct s_copy;
SomeHelperClass->SomeQueue.dequeue( &s_copy );
// do work that takes time to complete
// IS IT SAFE TO CALL THIS CALLBACK FUNCTION?
s_copy.callback(true);
});
}
So my question is given that code if its safe to have something like this?
void method_1()
{
void (*foo)(bool) = [](bool completedCorrectly)
{
cout << "task completed :" << completedCorrectly << endl;
};
some_method(1,2,foo);
// at this point foo should be deleted no?
// why does this work if foo is executed after method_1 completes and its stack is deleted?
// can I have code like that?
}
Edit 2
Here is the same question with working code instead of pseudo code:
#include <iostream> //for using cout
using namespace std; //for using cout
// 3 pointers
int* _X; // points to integer
int* _Y; // points to integer
void (*_F)(int); // points to function
void print_values()
{
cout << "x=" << *_X << " and y=" << *_Y << endl;
}
void some_function()
{
// create variables that live on stack of some_function
int x = 1;
int y = 2;
void (*foo)(int) = [](int someInt)
{
cout << "value passed to lambda is:" << someInt << endl;
};
// point global variables to variables created on this stack x,y and foo
_X = &x;
_Y = &y;
_F = foo;
// works
_F(11);
// works
print_values();
// when exiting variables x,y and foo should be deleted
}
int main(void)
{
// call some function
some_function();
// DOES NOT WORK (makes sense)
print_values();
// WHY DOES THIS WORK? WHY FOO IS NOT DISTROYED LIKE X AND Y?
_F(10);
return 0;
}
If I where to call that method many times and each time with a different lambda will it work? Will the callback method call the correct lambda every time?
A lambda expression is like a class. It is a blueprint for instantiating objects. Classes exist only in source code. A program actually works with objects created from the blueprint defined by a class. Lambda expressions are a source code blueprint for creating closures. Each lambda expression is transformed into a class by the compiler and instantiated into an object called closure. This class has the ability to capture values (that's that the [] part does) and take parameters (that's that the () part does) for its call operator.
Here is an example:
int main()
{
int i = 42;
auto l = [i](int const x){std::cout << x+i << '\n';};
l(2);
}
The compiler transforms this into something similar to the following (generated with https://cppinsights.io/).
int main()
{
int i = 42;
class __lambda_6_11
{
public:
inline /*constexpr */ void operator()(const int x) const
{
std::operator<<(std::cout.operator<<(x + i), '\n');
}
private:
int i;
public:
__lambda_6_11(int & _i)
: i{_i}
{}
};
__lambda_6_11 l = __lambda_6_11{i};
l.operator()(2);
}
You can see here a class that implements the call operator (operator()) with an int argument. You can also see the constructor taking an argument of type int. And then you can see the instantiation of this class at the end of main and the invocation of its call operator.
I hope this helps you understand better how lambdas work.
I am completely new to structs and user defined datatypes, and i was trying to create a function that returns a struct:
The problem is highlight by the comment:
#include <iostream>
using namespace std;
struct num {
int n[2];
};
num func( num x, int a, int b) {
x.n[0] = a+b;
x.n[1] = a*b;
return x;
}
int main() {
int x,y;
num s1;
cout << "enter: ";
cin >> x >> y;
func(s1,x,y);
cout << s1.n[0] << "\n" << s1.n[1]; // THIS GIVES ERROR
cout << func(s1,x,y).n[0] << "\n" << func(s1,x,y).n[1]; // THIS DOENST GIVE ERROR
return 0;
}
I understand that second method makes sense and returns the struct variable. then putting a dot addresses the inner variable of struct.
But i dont understand why first method fails, or gives odd output. The function has done its job, ie made s1.n[0] = x + y and s1.n[1] = x*y
Now, printing s1.n[0] should print x + y only. How can we check and correct the internal workings of the function?
You have to assign the returned value to the structure object in main
s1 = func(s1,x,y);
Inside the body the function deals with a copy of the original object. It does not change the original object because it is passed by value.
Another approach is to pass the structure by reference
void func( num &x, int a, int b) {
x.n[0] = a+b;
x.n[1] = a*b;
}
In this case in main you could just write
func(s1,x,y);
Or you could use even so-called C approach of passing by reference
void func( num *x, int a, int b) {
x->n[0] = a+b;
x->n[1] = a*b;
}
and call it like
func( &s1, x, y );
As for this statement
cout << func(s1,x,y).n[0] << "\n" << func(s1,x,y).n[1];
then you access data members of two temporary objects returned by the two calls of the function. After executing this statement these temporary objects will be deleted.
It looks like you are never assigning the return value of func(). Your function returns the struct, but you are never assigning it. To fix this, you should be able to simply say: s1 = func(s1,x,y); This will assign the modified version of the struct to the s1 variable.
Alternatively, you could rewrite func() to accept a pointer to the struct. This would allow you to modify the struct without having to return it:
void func( num *x, int a, int b) {
x->n[0] = a+b;
x->n[1] = a*b;
}
Then you would just change your call to func() to say: func(&s1, x, y);
You are not passing your struct by reference, hence the result. Try the following:
void func(num &x, int a, int b) {
x.n[0] = a+b;
x.n[1] = a*b;
}
There's no need for the function to return anything since your struct is passed by reference and it will be changed anyway. Void would fit better.
This is because you have passed the struct by value while your intentions look like you want to pass by reference.
Check this link : http://courses.washington.edu/css342/zander/css332/passby.html
num func( num &x, int a, int b)
should fix your problem
Example code:
#include <cstdlib>
#include <iostream>
using namespace std;
class A {
public:
A(int x, int y) : x(x), y(y) {}
int x, y;
};
class B {
public:
operator A() {
return A(x,y);
}
float x, y;
};
void func1(A a) {
cout << "(" << a.x << "," << a.y << ")" << endl;
}
void func2(A *a, int len) {
for(int i=0; i<len; ++i) {
cout << "(" << a->x << "," << a->y << ")";
}
cout << endl;
}
int main(int argc, char** argv) {
B b[10];
func1(b[0]);
//func2(b, 10);
return(EXIT_SUCCESS);
}
func1 works as expected, but func2 throws a compile-time error. Is there anything I can add to class B to make this work? I suspect not, but it doesn't hurt to ask, right?
I assume it won't work because the size of A is different from the size of B?
void func2(A *a, int len)
When you try to pass a pointer of type B to func2 there is no acceptable conversion from B* to A*. These are two different types from A and B, though the type B has a conversion operator to type A.
When you pass array to a method you are only passing the address of the first element not the actual copy of the array nor the first element.
In func1 you pass first element of array which is object of class B. Because B has operator A() it can convert B to A and new object of class A is passed to func1
In func2 you pass pointer to an array of B objects which is not the same as array of A objects so you get error.
To solve it you could have a transformation method that takes pointer to array of B's and iterators over it and for each calls func1 or something like that.
The other answers have addressed the core issue. But for completeness, it's worth noting that
I assume it won't work because the
size of A is different from the size
of B?
is incorrect.
First, A and B as given in this example would actually be the same size on many current compilers.
But even when A and B are the same size, the compiler will not perform this kind of conversion automatically. In fact, even if they have the exact same memory layout of member variables, the compiler will still not do it.
Consider following class
class test
{
public:
test(int x){ cout<< "test \n"; }
};
Now I want to create array of 50 objects of class test . I cannot change class test.
Objects can be created on heap or stack.
Creating objs on stack is not possible in this case since we dont have default constructor in class
test objs(1)[50]; /// Error...
Now we may think of creating objs on heap like this..
test ** objs = NULL;
objs = (test **) malloc( 50 * sizeof (test *));
for (int i =0; i<50 ; ++ i)
{
objs[i] = new test(1);
}
I dont want to use malloc .Is there any other way??
If you guys can think of some more solutions , please post them...
You cannot create an array of objects, as in Foo foo [N], without a default constructor. It's part of the language spec.
Either do:
test * objs [50];
for() objs[i] = new test(1).
You don't need malloc(). You can just declare an array of pointers.
c++decl> explain int * objs [50]
declare objs as array 50 of pointer to int
But you probably ought to have some sort of automatic RAII-type destruction attached.
OR subclass test publicly:
class TempTest : public test
{
public:
TempTest() : test(1) {}
TempTest(int x) : test(x) {}
TempTest(const test & theTest ) : test(theTest) {}
TempTest(const TempTest & theTest ) : test(theTest) {}
test & operator=( const test & theTest ) { return test::operator=(theTest); }
test & operator=( const TempTest & theTest ) { return test::operator=(theTest); }
virtual ~TempTest() {}
};
and then:
TempTest array[50];
You can treat every TempTest object as a test object.
Note: operator=() & copy constructor are not inherited, so respecify as necessary.
Why do you need array?
std::vector<test*> v(50);
Or as #j_random_hacker suggested in the comments:
std::vector<test> v(50, test(1));
An example:
/** g++ -Wall -o vector_test *.cpp && vector_test */
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct Test {
int value;
Test(int x) : value(x)
{
std::cout << "Test(" << value << ")" << " ";
}
operator int() const
{
std::cout << "int(" << value << ")" << " ";
return value;
}
};
int main()
{
using namespace std;
vector<Test> v(5, Test(1));
cout << endl;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
v[1] = 2;
v[2].value = 3;
cout << endl;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
Output:
Test(1)
int(1) 1 int(1) 1 int(1) 1 int(1) 1 int(1) 1
Test(2)
int(1) 1 int(2) 2 int(3) 3 int(1) 1 int(1) 1
Contrary to what many people believe, you can actually create an array of objects that do not have a default constructor. What you cannot do is make it use a set of arguments for all constructor invokations. You just have to initialize all elements of it. That is, you can do the following:
#define PRINTT(z, n, initializer) initializer
test objs[50] = {
BOOST_PP_ENUM(50, PRINTT, 1) // yields 1, 1, 1, .... 1
};
#undef PRINTT
That will initialize all 50 elements with 1. boost::pp is used to print a 1 50 times in a row automatically.
I think that other responders are treating this question too literally.
If all you really want to do is make a "group" of 50 objects that you can treat as an array, then by far the easiest and most maintainable way of accomplishing what you're trying to do is:
std::vector<test> objs(50, test(1));
This declares a vector of 50 objects, each of which is a copy of test(1). A vector is basically a C++ growable array; although you may not need the growability, the fact that it can be called with a 2-arg constructor that copy-constructs each element is useful here.
You can use this more-or-less exactly like an array -- e.g. the 5th element is objs[4]. Performance is the same too -- the C++ standard guarantees that internally the elements are stored in a contiguous array.
You don't need malloc(). You can use new for the array of pointers, too:
test **objs = new test* [50];
Boost's Pointer Container library might come to rescue here. With boost::ptr_vector<T> you can hold a list of heap-allocated objects which can be even polymorphic (virtual functions), which isn't possible with simply std::vector<T>.
Unlike std::vector<T>, the objects won't be stored in subsequential memory addresses. Things like resizing the container however will be faster because the elements will keep their original memory addresses. The best bonus is, you don't need to call delete yourself: the contained objects will be destroyed when the ptr_vector goes out of scope. Example:
#include <boost/ptr_vector.hpp>
#include <iostream>
class test() {
protected:
int const i;
public:
explicit test(int i) : i(i) {}
virtual void who_am_i() const { std::cout << "I am test " << i << std::endl; }
};
class special_test : public test {
public:
explicit special_test(int i) : test(i) {}
virtual void who_am_i() const { std::cout << "I am special_test " << i << std::endl; }
};
int main() {
boost::ptr_vector<test> objs;
for (int i=0; i<50; ++i)
objs.push_back(new test(i)); // NB: constructing to heap here!
objs.push_back(new special_test(123)); // objs can also hold inherited classes
objs[13].who_am_i(); // outputs: I am test 13
objs[50].who_am_i(); // outputs: I am special_test 123
} // all created objects are automatically destroyed here