Miranda functions and Initialization

J

JKop

Is this them all?:


class Dummy
{
public:

Dummy() {}

Dummy(const Dummy& original) { }

Dummy& operator=(const Dummy& lhs) {}

const Dummy * operator&() const { return this; }

Dummy * operator&() { return this; }

~Dummy() {}

};


Also could anyone please inform me of circumstances in which these are
edited and in which they disappear? For example I'm already aware of the
following:

1) Dummy() disappears if you supply another one that takes arguments, eg.
Dummy(int).

2) operator= and the copy constructor will change for every extra member
variable that's added to the class.


--

Now, take the following:

int main()
{
int j;
}


I'm fully aware that j contains no particular value, it hasn't been
initialized.

Now take the following:

int main()
{
int j = 45;
}

I'm fully aware that that's equal to:

int j = int(45);

But, where you have user-defined types, what exactly goes on?

For instance:

SomeClass k = 78.222;


Does that become:

SomeClass k = SomeClass(78.222);

And then is the SomeClass(const SomeClass&) copy constructor called? Or...
does the compiler simply look for a different copy constructor, eg.
SomeClass(const double&)? Or is that even valid?

Anyway here's what I'm getting at: I know int() is equal to zero, ie. if you
specify brackets then it gets intialized to zero. Now ofcourse you have the
problem of:

int main()
{
int j();
}

The compiler doesn't know if it's an object definition or a function
declaration (...if only "extern" was compulsory). As such, it assumes a
function declaration.

Is the only way to get around this to write:

int j(0);

?

Anyway here comes my question:

class Chocolate
{
public:

int a;

double b;

};


int main()
{
Chocolate choco;
}


Do "a" and "b" get initialized to zero? And if so, what does it? Is it the
miranda default constructor? What about in the following code:

class Chocolate
{
public:

int a;

double b;

Chocolate() {}

};


int main()
{
Chocolate choco;
}


Do "a" and "b" get initialized to zero in the above?


-JKop
 
J

John Harrison

Anyway here comes my question:

class Chocolate
{
public:

int a;

double b;

};


int main()
{
Chocolate choco;
}


Do "a" and "b" get initialized to zero?

No, the compiler generated default ctor leaves scalar types uninitalised.
And if so, what does it? Is it the
miranda default constructor? What about in the following code:

class Chocolate
{
public:

int a;

double b;

Chocolate() {}

};


int main()
{
Chocolate choco;
}


Do "a" and "b" get initialized to zero in the above?

Again no. The default ctor you wrote is identical to the compiler
generated default ctor, it leaves a and b uninitialised.

You can write this

Chocolate choco = Chocolate();

which would zero initalise a and b in the first definition of Chocolate
you gave but not in the second. Chocolate() is value initialsation which
differs from default initialisation in that it zero initialises scalar
types in a class without a user declared ctor.

john
 
R

Rolf Magnus

JKop said:
Is this them all?:


class Dummy
{
public:

Dummy() {}

Dummy(const Dummy& original) { }

Dummy& operator=(const Dummy& lhs) {}

const Dummy * operator&() const { return this; }

Dummy * operator&() { return this; }

~Dummy() {}

};


Also could anyone please inform me of circumstances in which these are
edited and in which they disappear? For example I'm already aware of
the following:

1) Dummy() disappears if you supply another one that takes arguments,
eg. Dummy(int).

The compiler won't generate a default constructor for you if you write a
user defined one, if that's what you mean.
2) operator= and the copy constructor will change for every extra
member variable that's added to the class.

They just do a memberwise copy. So yes, you could say that they change
when you add members to your class.
--

Now, take the following:

int main()
{
int j;
}


I'm fully aware that j contains no particular value, it hasn't been
initialized.

Now take the following:

int main()
{
int j = 45;
}

I'm fully aware that that's equal to:

int j = int(45);

But, where you have user-defined types, what exactly goes on?

For instance:

SomeClass k = 78.222;


Does that become:

SomeClass k = SomeClass(78.222);
Yes.

And then is the SomeClass(const SomeClass&) copy constructor called?
Yes.

Or... does the compiler simply look for a different copy constructor,
eg. SomeClass(const double&)?

That's not a copy constructor, but a conversion constructor. And yes,
that one is needed, two. First, a nameless temporary object of class
SomeClass is created using that constructor, then k is copy-constucted
from that one. Note however, that the C++ standard gives explicit
permission to directly create k from the double value, omiting the
temporary, but even if the copy constructor is never called, it still
has to be available. If, however, you write:

SomeClass k(78.222);

only the conversion constructor from double is needed and the copy
constructor is not involved.
Or is that even valid?

Anyway here's what I'm getting at: I know int() is equal to zero, ie.
if you specify brackets then it gets intialized to zero.

Yes. This constructor-style initialization can come in handy in
templates.
Now ofcourse you have the problem of:

int main()
{
int j();
}

The compiler doesn't know if it's an object definition or a function
declaration (...if only "extern" was compulsory). As such, it assumes
a function declaration.

Well, the above _is_ a function declaration.
Is the only way to get around this to write:

int j(0);

?

No. You can do:

int j = int();

But usually, I'd just write the more intuitive:

int j = 0;
Anyway here comes my question:

class Chocolate
{
public:

int a;

double b;

};


int main()
{
Chocolate choco;
}


Do "a" and "b" get initialized to zero?

No. They stay uninitialized.
And if so, what does it? Is it the miranda default constructor?

It's the (empty) compiler-generated default constructor.
What about in the following code:

class Chocolate
{
public:

int a;

double b;

Chocolate() {}

};


int main()
{
Chocolate choco;
}


Do "a" and "b" get initialized to zero in the above?

You didn't write any code to initialze a or b, so they don't get
initialized.
 
J

JKop

#include <string>

class Cheese
{
public:

int a;
double b;
std::string name;
};


int main()
{
Cheese mouse;
}


So in the above, "a" and "b" contain white noise, while "name" has been
constructed properly.

Is there any way I can turn the function declaration into an object
definition?!

I see that I can do:

Cheese mouse = Cheese();

Is that the *only* way?

So anyway...

I see in a lot of Win32 documentation that when they have a structure that's
to be passed to a Win32 function, like:

struct SETTINGS
{
int AMOUNT_PORTS;
bool ANY_OPEN;
unsigned char* SET_ID;
};


that in the code they have:


SETTINGS sets;
memset(&sets,0,sizeof(sets));

So instead of that can one write:

SETTINGS sets = SETTINGS();

Another thing with my way, any pointer variables are given they're proper
null pointer value, as opposed to just 0.


BTW, I've also just noticed lately that you can do the following:

extern void Blah(unsigned long);
extern void Blah(unsigned);
extern void Blah(unsigned short);

int main()
{
Blah(unsigned short(52U));
}


Happy Days!


-JKop
 
J

JKop

In the following, are "Dummy" and "DummyClone" identical?

#include <string>

class Dummy
{
private:

int a;

protected:

std::string name;

public:

double k;
};


class DummyClone
{
private:

int a;

protected:

std::string name;

public:

double k;

public:

DummyClone() {}

DummyClone* operator&() { return this; }
const DummyClone* operator&() const { return this; }

DummyClone(const DummyClone& original)
{
a = original.a;
name = original.name;
k = original.k;
}

DummyClone& operator=(const DummyClone& lhs)
{
a = lhs.a;
name = lhs.name;
k = lhs.k;
}

~DummyClone() { }
};


int main()
{
Dummy x;

DummyClone y;

}


Have I left out any miranda functions? Are there 6 in all?

-JKop
 
A

Alf P. Steinbach

* JKop:
I see in a lot of Win32 documentation that when they have a structure that's
to be passed to a Win32 function, like:

struct SETTINGS
{
int AMOUNT_PORTS;
bool ANY_OPEN;
unsigned char* SET_ID;
};


that in the code they have:


SETTINGS sets;
memset(&sets,0,sizeof(sets));

So instead of that can one write:

SETTINGS sets = SETTINGS();

In theory yes, in practice no, because many compilers do not respect
the standard in this regard.

Instead write


SETTINGS sets = {0};


Often the following idiom is useful:


SOME_MS_UPPERCASE_TYPE ugh = {sizeof(ugh)};
STATIC_ASSERT( offsetof( SOME_MS_UPPERCASE_TYPE, hnSize ) == 0 );


You can find a nice implementation of STATIC_ASSERT in e.g. the
Another thing with my way, any pointer variables are given they're proper
null pointer value, as opposed to just 0.

0 is the null value for pointers.
 
D

David Hilsee

0 is the null value for pointers.

I think he's talking about the difference between "all bits zero" and a null
pointer. While the literal zero can be used to signify a null pointer, that
doesn't mean that a null pointer must have a representation where all of its
bits are zero.
 
J

JKop

Alf P. Steinbach posted:
In theory yes, in practice no, because many compilers do not respect
the standard in this regard.

Please explain what you mean - are you saying that not
many compilers will compile the above as specified by the
Standard?
0 is the null value for pointers.

Not necessarily. And the Standard provides for this. Where
you write:

int* k = 0;

It replaces 0 with the appropriate null pointer value.

But when you use memset, there's no replacement.

-JKop
 
A

Alf P. Steinbach

* JKop:
Alf P. Steinbach posted:


Please explain what you mean - are you saying that not
many compilers will compile the above as specified by the
Standard?

Yes.
 
R

Rolf Magnus

JKop said:
In the following, are "Dummy" and "DummyClone" identical?
No.

#include <string>

class Dummy
{
private:

int a;

protected:

std::string name;

public:

double k;
};


class DummyClone
{
private:

int a;

protected:

std::string name;

public:

double k;

public:

DummyClone() {}

DummyClone* operator&() { return this; }
const DummyClone* operator&() const { return this; }

DummyClone(const DummyClone& original)
{
a = original.a;
name = original.name;
k = original.k;
}

The compiler generated copy constructor will do a memberwise copy
initializiation, while you do a default (or in the case of built-in
types no) initialization, followed by an assignment. This makes a
difference for the std::string member, which first gets
default-construted and then assigned, instead of copy-constructed. A
copy constructor that does the same as the compiler generated one would
do looks like this:

DummyClone(const DummyClone& original)
: a(original.a),
name(original.name),
k(original.k)
{
}
DummyClone& operator=(const DummyClone& lhs)
{
a = lhs.a;
name = lhs.name;
k = lhs.k;
}

~DummyClone() { }
};


int main()
{
Dummy x;

DummyClone y;

}


Have I left out any miranda functions? Are there 6 in all?

-JKop

--
Kyle: "Hey, Stan, now that Terrance & Phillip has been taken off the
air, what
are we gonna do for entertainment?"
Stan: "I don't know. We, we could start breathing gas fumes."
Cartman: "My uncle says that smoking crack is kinda cool"
Kyle: "Hey, why don't we watch some of those porno movie thingies?"
 
J

JKop


What do they do instead?

In the absence of optimization, here's what should happen:

1) A SETTINGS object is created, all values intialized to 0.
2) sets is copy-constructed from the previous object.
3) The original object is destroyed.

And with optimization:

1) sets is created, all values initialized to 0.


Where do these other alleged C++ compilers go wayward?


-JKop
 
J

JKop

Thanks Rolf.

So now we have:

#include <string>

class Dummy
{
private:

int a;

protected:

std::string name;

public:

double k;
};


class DummyClone
{
private:

int a;

protected:

std::string name;

public:

double k;

public:

DummyClone() {}

DummyClone* operator&() { return this; }
const DummyClone* operator&() const { return this; }

DummyClone(const DummyClone& original)
: a(original.a), name(original.name), k(original.k) {}

DummyClone& operator=(const DummyClone& lhs)
{
a = lhs.a;
name = lhs.name;
k = lhs.k;
}

~DummyClone() { }
};


int main()
{
Dummy x;

DummyClone y;
}


Is that it now?


-JKop
 
A

Alf P. Steinbach

* JKop:
What do they do instead?

In the absence of optimization, here's what should happen:

1) A SETTINGS object is created, all values intialized to 0.
2) sets is copy-constructed from the previous object.
3) The original object is destroyed.

And with optimization:

1) sets is created, all values initialized to 0.

Where do these other alleged C++ compilers go wayward?

According to my notes Visual C++ 7.0 is one such alleged compiler... ;-)

Visual C++ 7.1 seems to do it right.
 
J

John Harrison

Thanks Rolf.

So now we have:

#include <string>

class Dummy
{
private:

int a;
protected:

std::string name;
public:

double k;
};


class DummyClone
{
private:

int a;
protected:

std::string name;
public:

double k;

public:

DummyClone() {}
DummyClone* operator&() { return this; }
const DummyClone* operator&() const { return this; }
DummyClone(const DummyClone& original)
: a(original.a), name(original.name), k(original.k) {}
DummyClone& operator=(const DummyClone& lhs)
{
a = lhs.a;
name = lhs.name;
k = lhs.k;
}

~DummyClone() { }
};


int main()
{
Dummy x;
DummyClone y;
}


Is that it now?


-JKop

Dummy and DummyClone still differ if value initialised

Dummy* d = new Dummy();
DummyClone* dc = new DummyClone();

Here d->a and d->k are guaranteed to be zero (assuming you have a compiler
which implements value initialisation correctly) but dc->a and dc->k are
uninitialised.

john
 
J

John Harrison

What do they do instead?

In the absence of optimization, here's what should happen:

1) A SETTINGS object is created, all values intialized to 0.
2) sets is copy-constructed from the previous object.
3) The original object is destroyed.

And with optimization:

1) sets is created, all values initialized to 0.


Where do these other alleged C++ compilers go wayward?


-JKop

I think many would fail to iniitalise to zero. As I understand it this was
acceptable pre-2003 standard.

john
 
J

JKop

Dummy and DummyClone still differ if value initialised
Dummy* d = new Dummy();
DummyClone* dc = new DummyClone();

Here d->a and d->k are guaranteed to be zero (assuming you have a
compiler which implements value initialisation correctly) but dc->a
and dc->k are uninitialised.

john


And there's no way around this?

Also I presume that if you leave it like:

Dummy* d = new Dummy;

the it contains white noise, yes?

Now here's a tricky one:

A class that has only public data, but it has a contructor:

class Chunky
{
public:
int a;
double b;
char c;

Chunky() {}
};


If I do:

Chunky chunks;

Then "a", "b" and "c" contain white noise. That right?

While if I do:

Chunky chunks = Chunky();

Then it still contains white noise (on account of the constructor). That
right?

What I'm getting at is if a certain class has a contructor, are:

Chunk chunks;
Chunky chunks = Chunky();

identical, in that they both contain white noise?


-JKop
 
J

John Harrison

JKop said:
And there's no way around this?

I don't think so.
Also I presume that if you leave it like:

Dummy* d = new Dummy;

the it contains white noise, yes?
Yes.


Now here's a tricky one:

A class that has only public data, but it has a contructor:

class Chunky
{
public:
int a;
double b;
char c;

Chunky() {}
};


If I do:

Chunky chunks;

Then "a", "b" and "c" contain white noise. That right?
Right.


While if I do:

Chunky chunks = Chunky();

Then it still contains white noise (on account of the constructor). That
right?

Right, value initialisation only makes a difference (as far as I can tell)
for types without a constructor.
What I'm getting at is if a certain class has a contructor, are:

Chunk chunks;
Chunky chunks = Chunky();

identical, in that they both contain white noise?

It depends on the default constuctors of course, but otherwise both are
identical.

john
 
J

JKop

Which leads me on to POD types.

For instance, take the following:

#include <string>

class Cow
{
public:
int a;
double b;
std::string c;
};

int main
{
Cow dairy_cow = { 5, 67.2, std::string("Moo!") };
}


It looks like a type is no longer a POD when the above syntax in "main" is
no longer valid. For instance, take:


class Cow
{
public:
int a;
double b;
std::string c;

private:

char t;
};

int main
{
Cow dairy_cow = { 5, 67.2, std::string("Moo!") };
}


Now the compiler is telling me that a "Cow" can't be defined like that, and
that you've to use a constructor.

I've found the following things render a class no longer a POD:

a) Putting in private or protected member data
b) Putting in a constructor or copy-constructor

And that the following are no problem, it's still a POD:

a) Putting in member functions
b) Putting in operator member functions
(even if they're private or protected)


It's good to know this stuff!

So now I think I fully understand all the initialization stuff in C++.


There's just one thing that I want to figure out:

SomeClass object = SomeClass();


There has to be some sort of way of turning the following:

SomeClass object();

into an object definition. I've tried:

class SomeClass object();
struct SomeClass object();

But still they're a function declaration. That doesn't make sense to me.
It'd even be compatible with C, because while you would prefix "struct" in
C, you still wouldn't put in parenthesis. And there was no "class" in C
either.

Anyone know how to tell the compiler it's an object definition?


-JKop
 
O

Old Wolf

JKop said:
In the following, are "Dummy" and "DummyClone" identical?
[some stuff snipped from these definitions]
class Dummy
{
};

class DummyClone
{
public:
DummyClone* operator&() { return this; }
const DummyClone* operator&() const { return this; }
};

No. DummyClone contains operator& and Dummy does not. You also made
this mistake in your original post.
int main()
{
Dummy x;
DummyClone y;

}

Have I left out any miranda functions? Are there 6 in all?

You included too many. Don't be misled by mistakes in the book
'C++ by Dummies' (which also invented the term 'miranda functions').

If you don't believe it, add these lines to main:

& DummyClone::eek:perator &;
& Dummy::eek:perator &;

and note the compiler error.
 
J

JKop

Old Wolf posted:
You included too many. Don't be misled by mistakes in the book
'C++ by Dummies' (which also invented the term 'miranda functions').

If you don't believe it, add these lines to main:

& DummyClone::eek:perator &;
& Dummy::eek:perator &;

and note the compiler error.

Although the following *does* compile:

class Dummy {};

void Blah(Dummy* a) {}
void Blah(const Dummy*) {}

int main()
{
Dummy k = Dummy();
const Dummy j = Dummy();

Blah(&k);
Blah(&j);
}


-JKop
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top