See my code below:
class A
{
public:
A()
{
i = 0;
if(pt != NULL)
{
std::cout << "why" << std::endl;
}
}
A(bool flag)
{
i = 0;
pt = new B(3.14);
}
private:
class B
{
public:
B(double in) : j(in) {}
private:
double j;
};
private:
int i;
B *pt;
};
int main(int argc, char *argv[])
{
A obj; // place1
int *p;
if(p != NULL)
{
std::cout << "test2" << std::endl;
}
return 0;
}
In this piece of code, I wonder to know if pt will be initialized #place1.
The other question is that if I delete the definition of obj, test2 will print, if not, then why?
Value of p is undefined. It may be 0 or 1 or 2 or ......
So if it is your lucky day, you may get a print otherwise not.
Moral: Don't rely on what you get, initialize variables by yourself.
In this piece of code, I wonder to know if pt will be initialized #place1.
It is not initialized to anything. Technically, it is default-initialized, which for a pointer means no initialization is performed. This means it can hold any value, and it is undefined behaviour to read from it.
In C++11, if you hav value-initialized obj, then pt would be zero-initialized:
A obj{}; // obj.pt is nullptr
The other question is that if I delete the definition of obj, test2 will print, otherwise not, why?
p has an undetermined value too. It can be NULL, but it may not be. Reading from it is undefined behaviour too. So, it can take the value of NULL sometimes, sometimes not, and you cannot rely on and predictable behaviour.
According to the C++ Standard local variables are not initilized implicitly. So in this code snippet
int main(int argc, char *argv[])
{
// ...
int *p;
// ...
p is not initialized by the compiler implicitly because p is a local variable. It could be zero-initialized if p had static storage duration. For example
int *p;
int main(int argc, char *argv[])
{
// ...
In this code snippet variable p will be zero initialized.
As for the class A then in this code snippet
int main(int argc, char *argv[])
{
A obj; // place1
object obj will be default initialized that is the default constructor of the class will be called. As you do not initialize data member pt in the constructor its value will be undefined.
Again if the object had static storage duration then at first the memory occupied by the object would be zero-initialized before calling the default constructor. In this case pt would be zero-initialized
A obj;
int main(int argc, char *argv[])
{
Pointers are not initialized by default. You need to initialize it in your constructor (for members) or at the place of declaration (for local variables)
C++ will not initialize your instance variables for you. As long as you don't set them to a value, they will have a random value (or some value that looks like random garbage).
if(pt != NULL)
will be probably true since pt is not initialized to NULL in code it can be any value. pointer should be initialized to NULL in code by the programmer.
you can read this related question. to know about it.
Related
Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.
So I'm looking for clarification on something that works. I'm pretty sure I understand what is happening but wanted to be sure before proceeding with my work.
I have a function defined as follows:
name* createName(char* firstName, char* lastName)
{
name* newName = (name*)malloc(sizeof(name));
initStringValue(&newName->firstName, firstName);
initStringValue(&newName->lastName, lastName);
newName->firstNameSize = strlen(newName->firstName);
newName->lastNameSize = strlen(newName->lastName);
return newName;
}
The structure "name" is defined like so:
struct name
{
char* firstName;
char* lastName;
int firstNameSize;
int lastNameSize;
};
Another function responsible for the copy of the name strings is written like the following:
void initStringValue(char** destination, char* source)
{
int length = strlen(source) + 1;
int size = length * sizeof(char);
*destination = (char*)malloc(size);
memset(*destination, 0, size);
strcpy(*destination, source);
}
If I'm understanding what I've done here, by using the & operator I've signified that I wish to send not a value but its associated memory address. In a statement such as
&newName->firstName
where the struct member firstName is a char* I've indicated that I would like to send the memory address of this pointer and not the pointers value (which happens to be a memory address in and of itself). The -> operator dereferences this pointer to the member of the pointer but then the & operator essentially returns us to the firstName memory reference instead, allowing me to manipulate information at that memory reference.
Now things get wild (for me anyway). To actually work with that memory reference, I end up using double indirection (so very passive aggressive). As it follows a memory reference (like that of &newName->firstName) sent to a char** like that of char** destination in the initStringValue function, would be a pointer of a pointer where the latter is assigned the memory reference returned by &newName->firstName. By then using *destination I'm working with a pointer pointed to the memory reference of &newName->firstName. Or stated differently, a pointer whose first and only member is the memory reference of newName->firstName.
Am I actually understanding this correctly?
Am I actually understanding this correctly?
After reading your description, I'll say yes
I'll try to explain it with some examples.
If you do this:
void foo(int a)
{
a = 5;
}
int main()
{
int a = 10;
foo(a);
printf("%d\n", a);
return 0;
}
You'll get the output: 10
That's because the function parameters are local variables to the function. In other words - any change made to a function parameter is lost when the function returns, i.e. the variable in main will not be changed.
If you want a function to change the value of a variable in main (aka in the caller), you'll have to pass a pointer. Like:
void foo(int* a) // notice int*
{
*a = 5; // notice *a
}
int main()
{
int a = 10;
foo(&a); // notice &a
printf("%d\n", a);
return 0;
}
This will output: 5
This is a general rule regardless of the type. I used int in the example but it applies to any type - pointers as well.
So let's take an example with a pointer:
void foo(char** a, int size) // notice char**
{
*a = malloc(32); // malloc memory
strcpy(*a, "Hello world"); // copy some data into the memory
}
int main()
{
char* a = NULL; // a is not pointing to anything yet
foo(&a);
// Now a points to the malloc'ed memory
printf("%s\n", a);
return 0;
}
This will output: Hello world
i am getting error in this code
class business
{
public:
business(); // Default Constructor
business(string busines,int r)
{
busines=busines;
ratings=r;
} // constructor;
private:
string busines;
int ratings;
int items_owned;
int business_cancellation;
int biz_size_of_building;
int biz_shipping_method;
};
int main(int argc, char *argv[])
{
business b[10];
b[b_count](busines,rating);
return 0;
}
It gives me the following error (http://ideone.com/FfajNS):
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:32:32: error: no match for call to ‘(business) (std::string&, int&)’
You're attempting to call a constructor on an already constructed object ... the default constructor was called during the array creation, therefore you cannot "construct" the object again. For your application, you may want to look into using a std::vector where you can create a array-like container using an object initialized from a set of default arguments.
For instance, you could do:
std::vector<business> array(10, business(business_string, rating));
I believe you want something like this:
b[2] = business("Denny's", 50);
This creates a temporary business variable by calling the constructor with the given parameters. The temporary is then copied into slot 3 of the array b.
The array b already created 10 business objects using the default constructor of that class. You can access those objects by business someBusiness = b[someIndex];
edit:
If you want to set the values of your individual objects, simply do this (notice, that you don't create these objects, just set their values):
for(int i=0; i<10; i++)
{
b[i].busines = ...;
b[i].ratings = ...;
/* or to create new ones */
b[i] = business("asd", 10);
}
It would be even better, if you stored these objects in vector, like Jason suggested
business b[10];
You create 10 "default" business object. What is b_count? I hope some int from 0 to 9.
But here you are "calling" a business object with 2 arguments:
b[b_count](busines,rating);
But business have no operator()() defined with 2 parametr.
EDIT:
You definitely have to use std::vector and carefully read the other answers.
But I know that on occasion beginners are not allowed to use the STL library, and anyway it seems that you should understand how constructors are used and how the elements of an array are initialized. Please read about static members and how they are defined and try to understand how the following example works.
#include <string>
using std::string;
class business
{
public:
business() // Default Constructor
:busines(def_busines),ratings(def_ratings){};
business(const string& bus,int r) // constructor;
:busines(bus),ratings(r){}
static void SetDef(const string& busines,int r)
{
def_busines=busines;
def_ratings=r;
}
private:
string busines;
int ratings;
static string def_busines;
static int def_ratings;
int items_owned;
int business_cancellation;
int biz_size_of_building;
int biz_shipping_method;
};
string business::def_busines=""; // Set here the default-defaults
int business::def_ratings=1;
int main(int argc, char *argv[])
{
business::SetDef("Some business",2);
business a[10];
business::SetDef("Other business",3);
business b[10];
business c("Third business",4);
return 0;
}
I have 3 classes.
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
[custructor with/without param, display function - works well each one of it]
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
[custructor with/without param, display function - works well each one of it]
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
void afisare()
{
cout<<nr;
}
In main i have this:
piesa_c C(2, H,14,"TIPC",20);
C.afisare();
But this doesn't work.
I don't know if the "buf" was declared properly because the problem seems to be in last class.
Why?
Later Edit:
The entire code is here: http://pastebin.com/nx2FGSfe.
Now, i have this in main
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
The display function return this error
main.cpp:143:14: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
nr is not initialized in the piesa_c() constructor, meaning it will have an undefined value.
Instead of using a dynamically allocated array used a std::vector<piesa_b> instead. It will handle dynamic memory allocation and do the right thing when instances of piesa_c is copied. Using std::vector also means the nr member variable can omitted as that information can be obtained from vector::size() and the std::vector can be populated in the initializer list instead of in the constructor body:
std::vector<piesa_b> buf;
piesa_c(int n,
piesa_b *bu,
int aid,
char* tipi,
int pretzz) : piesa_a(aid,tipi,pretzz),
buf(bu, bu + nr) {}
And to invoke a member function on each element in buf:
// C++11 lambda, otherwise use
// std::vector<piesa_b>::const_iterator.
//
std::for_each(buf.begin(), buf.end(), [](piesa_b& pb) { pb.afisare(); });
If afisare() does not modify then make it const:
void afisare() const
{
}
Additonally, use std::string instead of char*. If you insist on having dynamically allocated members in the classes you need to obey the rule of three.
I am not sure what "not work" means in this context, but when you call this constructor:
piesa_c C(2, H,14,"TIPC",20);
the data member nr is not set. It can have any value that fits into an int, so when you use it to initialize an array you will get variable and weird results.
Note that you could save yourself a lot of trouble by using std::vector and std::string instead of dynamically allocated arrays and char*.
Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.