Default ctor, etc generated by compiler for structs?

J

JohnQ

Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not explicitely
defined?

I think the answer is yes, because "there is no difference between a struct
and a class except the public/private access specification" (and a few minor
other things). When I create a class, I always start by declaring the
default constructor, copy constructor and assignment operator private with
no implementation. I don't do that for structs though (I consider structs
like they were in C, but they really are not in the implementation as far as
I know). I'm thinking that I don't handle structs the same because I trust
the compiler to do the right thing in the case of structs whereas bitwise
copy for a class may not be what is desired, for example.

Is the above reasoning OK? Should I continue NOT declaring/defining the
default stuff for structs?

John
 
B

BobR

JohnQ said:
Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not explicitely
defined?

#include <vector>
struct Hmmm{ int mmm; };

{
std::vector<Hmmm> SVmmm(2);
std::vector<Hmmm> SVtwo;
SVtwo = SVmmm;
}

Can that work? Does it meet the requirements for a std container?
[ my tests say: yes, no problem, dude! ]
Now, add something non-simple to the struct, and test again.

I think the answer is yes, because "there is no difference between a struct
and a class except the public/private access specification" (and a few minor
other things). When I create a class, I always start by declaring the
default constructor, copy constructor and assignment operator private with
no implementation. I don't do that for structs though (I consider structs
like they were in C, but they really are not in the implementation as far as
I know). I'm thinking that I don't handle structs the same because I trust
the compiler to do the right thing in the case of structs whereas bitwise
copy for a class may not be what is desired, for example.

Is the above reasoning OK? Should I continue NOT declaring/defining the
default stuff for structs?
John

class A{ public: int a;}; == struct A{ int a;};
class A{ int a;}; == struct A{ private: int a;};

Or did I misunderstand something (again!).
 
I

Ian Collins

JohnQ said:
Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not
explicitely defined?

I think the answer is yes, because "there is no difference between a
struct and a class except the public/private access specification" (and
a few minor other things). When I create a class, I always start by
declaring the default constructor, copy constructor and assignment
operator private with no implementation. I don't do that for structs
though (I consider structs like they were in C, but they really are not
in the implementation as far as I know). I'm thinking that I don't
handle structs the same because I trust the compiler to do the right
thing in the case of structs whereas bitwise copy for a class may not be
what is desired, for example.

Is the above reasoning OK? Should I continue NOT declaring/defining the
default stuff for structs?
Apply the same rules as you apply to your classes. If you need to
initialise members on creation or copy, you need constructors.
 
J

Jim Langston

JohnQ said:
Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not
explicitely defined?

I think the answer is yes, because "there is no difference between a
struct and a class except the public/private access specification" (and a
few minor other things). When I create a class, I always start by
declaring the default constructor, copy constructor and assignment
operator private with no implementation. I don't do that for structs
though (I consider structs like they were in C, but they really are not in
the implementation as far as I know). I'm thinking that I don't handle
structs the same because I trust the compiler to do the right thing in the
case of structs whereas bitwise copy for a class may not be what is
desired, for example.

Is the above reasoning OK? Should I continue NOT declaring/defining the
default stuff for structs?

If your structure is POD, then there should be no reason not to allow the
compiler to create default constructor, destrucctor, copy constructor and
assignment operators. I would say it was okay, but I do not know for
exactly what reason you crete the 4 for classes (not saying it's a bad
thing, probably a very good thing, I just don't know your reasoning behind
it).
 
V

Victor Bazarov

JohnQ said:
Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not
explicitely defined?

If by a struct you mean POD, then yes, but only conceptually.
If by a struct you mean any class where you only specify data
members, then it depends on the data members.
I think the answer is yes, because "there is no difference between a
struct and a class except the public/private access specification"
(and a few minor other things). When I create a class, I always start
by declaring the default constructor, copy constructor and assignment
operator private with no implementation. I don't do that for structs
though (I consider structs like they were in C, but they really are
not in the implementation as far as I know). I'm thinking that I
don't handle structs the same because I trust the compiler to do the
right thing in the case of structs whereas bitwise copy for a class
may not be what is desired, for example.

What's "bitwise copy"? I don't know of that concept in C++.
Is the above reasoning OK? Should I continue NOT declaring/defining
the default stuff for structs?

It's up to you. And the ability of the compiler to generate the
functions you don't declare/define depends on the data members.

V
 
G

Gavin Deane


Perhaps, but it's not defined in C++. Of more direct relevance to the
OP though is that, regardless of whether we're all happy with that
definition of "bitwise copy", it's not what happens in the implicitly-
defined copy constructor, which does a memberwise copy.

Gavin Deane
 
B

Bharath

JohnQ said:
Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not explicitely
defined?

#include <vector>
struct Hmmm{ int mmm; };

{
std::vector<Hmmm> SVmmm(2);
std::vector<Hmmm> SVtwo;
SVtwo = SVmmm;

}

Can that work? Does it meet the requirements for a std container?
[ my tests say: yes, no problem, dude! ]
Now, add something non-simple to the struct, and test again.

Your program is not a right e.g for the question asked. I think this
would have been misunderstood by query submitter. In this case,
actually, vector template class will take care of constructor stuff
for statement "std::vector<Hmmm> SVmmm(2);", it's not default ctr of
struct Hmmm.

- Bharath
 
G

Gavin Deane

#include <vector>
struct Hmmm{ int mmm; };
{
std::vector<Hmmm> SVmmm(2);
std::vector<Hmmm> SVtwo;
SVtwo = SVmmm;

Can that work? Does it meet the requirements for a std container?
[ my tests say: yes, no problem, dude! ]
Now, add something non-simple to the struct, and test again.

Your program is not a right e.g for the question asked. I think this
would have been misunderstood by query submitter. In this case,
actually, vector template class will take care of constructor stuff
for statement "std::vector<Hmmm> SVmmm(2);"

Yes, and one of the things the vector constuctor will do is to default-
construct 2 objects of type to populate SVmmm.
it's not default ctr of
struct Hmmm.

The default constructor of Hmmm is necessary and is used. The code
demonstarates that struct Hmmm does have an implicitly-defined default
constructor and so does address the OP's question.

Gavin Deane
 
B

BobR

Bharath wrote in message...
Your program is not a right e.g for the question asked. I think this
would have been misunderstood by query submitter. In this case,
actually, vector template class will take care of constructor stuff
for statement "std::vector<Hmmm> SVmmm(2);", it's not default ctr of
struct Hmmm.
- Bharath

See this thread if you have doubts:

----- Original Message -----
From: BobR
Newsgroups: comp.lang.c++
Sent: Saturday, June 09, 2007 10:41 PM
Subject: Re: problems of storing dynamically created objects in a vector
 
B

BobR

BobR wrote in message...
#include <vector>
struct Hmmm{ int mmm; };

{
std::vector<Hmmm> SVmmm(2);

// add this to demonstrate the assignment operator is there:
SVmmm.at(0).mmm = 42;
SVmmm.at(1) = SVmmm.at(0); // use assignment
// cout<<SVmmm.at(1).mmm;
 
J

James Kanze

Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not
explicitely
defined?
#include <vector>
struct Hmmm{ int mmm; };
{
std::vector<Hmmm> SVmmm(2);
std::vector<Hmmm> SVtwo;
SVtwo = SVmmm;
}
Can that work? Does it meet the requirements for a std container?
[ my tests say: yes, no problem, dude! ]
Now, add something non-simple to the struct, and test again.
Your program is not a right e.g for the question asked. I think this
would have been misunderstood by query submitter. In this case,
actually, vector template class will take care of constructor stuff
for statement "std::vector<Hmmm> SVmmm(2);"
Yes, and one of the things the vector constuctor will do is to
default-construct 2 objects of type to populate SVmmm.

Just a nit, but the vector constructor will not
default-construct 2 objects. The compiler will
default-construct an argument to vector, which will copy this
object into the 2 objects in the vector.
 
J

JohnQ

Ian Collins said:
Apply the same rules as you apply to your classes. If you need to
initialise members on creation or copy, you need constructors.

I was pondering the technique of restricting default constructor, copy
constructor, assignment operator though and its validity for structs as well
as classes:

class A
{
A(); // disallow def construction
A(const A&); // disallow copy construction
const A& operator=(const A&); // disallow assignment

public
int data_member;

A(int arg)
: data_member(arg) {}
};

struct B
{
B(); // disallow def construction
B(const B&); // disallow copy construction
const B& operator=(const B&); // disallow assignment

int data_member; // public by default

B(int arg)
: data_member(arg) {}
};

If I disallow the stuff in struct B, it acts less like a C struct, yes?

John
 
J

JohnQ

Jim Langston said:
If your structure is POD, then there should be no reason not to allow the
compiler to create default constructor, destrucctor, copy constructor and
assignment operators.

That's what I was thinking. I wasn't sure if the compiler generates those
things for a POD struct. Are you sure?
I would say it was okay, but I do not know for exactly what reason you
crete the 4 for classes (not saying it's a bad thing, probably a very good
thing, I just don't know your reasoning behind it).

To prevent those things from happening unknowingly for what could be a
non-POD.

John
 
G

Gavin Deane

Are a default constructor, destructor, copy constructor and assignment
operator generated by the compiler for a struct if they are not
explicitely
defined?
#include <vector>
struct Hmmm{ int mmm; };
{
std::vector<Hmmm> SVmmm(2);
std::vector<Hmmm> SVtwo;
SVtwo = SVmmm;
}
Can that work? Does it meet the requirements for a std container?
[ my tests say: yes, no problem, dude! ]
Now, add something non-simple to the struct, and test again.
Your program is not a right e.g for the question asked. I think this
would have been misunderstood by query submitter. In this case,
actually, vector template class will take care of constructor stuff
for statement "std::vector<Hmmm> SVmmm(2);"
Yes, and one of the things the vector constuctor will do is to
default-construct 2 objects of type to populate SVmmm.

Just a nit, but the vector constructor will not
default-construct 2 objects. The compiler will
default-construct an argument to vector, which will copy this
object into the 2 objects in the vector.

.... thereby demonstrating the presence of an implicitly-defined copy
constructor for struct Hmmm as well as an implicitly-defined default
constructor - handily addressing even more of the OP's question.

Thanks for the nit.

Gavin Deane
 
J

JohnQ

Victor Bazarov said:
If by a struct you mean POD, then yes, but only conceptually.

Different from an identical class? Conceptually how?
If by a struct you mean any class where you only specify data
members, then it depends on the data members.

Lately, I've been pondering, "when does a struct stop being a struct?". To
me, that's when its not the same size as a C struct or not layed out the
same. So obviously, when a virtual function gets added, then "a struct stops
being a struct". I think I can add non-virtual member functions, non-virtual
destructor and operators ad infinitum and the "struct will still be a
struct" (right?). Even though some explicit syntax would make things more
evident:

struct A
{
int data;
};

struct B
{
int data;

B(int val){ data = val; } // OK, not virtual
};

class StructWrapper
{
A a_struct;

public:
A(int val){ a_struct.data = val; }
operator A&(){ return a_struct; }
};

Where struct B can be used identically to struct A or StructWrapper (I
hope!) as the layouts and sizes are the same (assume the operator is being
used for StructWrapper when I say "can be used identically").

sizeof(A)==sizeof(B)==sizeof(StructWrapper)

But a_struct in StructWrapper would have to be made public to guarantee the
same layout as A and B?
What's "bitwise copy"? I don't know of that concept in C++.

The equivalent of doing a memcpy of the class or struct (whether I used the
right terminology or not I don't know... "bytewise" seems more appropriate).
It's up to you. And the ability of the compiler to generate the
functions you don't declare/define depends on the data members.

OK, so from what I gather, the compiler may or may not generate the
functions/operators depending on the data members. Is it that if there is
any non-POD data member, then the functions/operators get generated? Is it
always the full set (?): default constructor, copy constructor, assignment
operator, (destructor?).

John
 
V

Victor Bazarov

JohnQ said:
[..]
struct B
{
B(); // disallow def construction
B(const B&); // disallow copy construction
const B& operator=(const B&); // disallow assignment

int data_member; // public by default

B(int arg)
: data_member(arg) {}
};

If I disallow the stuff in struct B, it acts less like a C struct,
yes?

As soon as you add a c-tor to B, it stops being a POD. Whether you
"disallow the stuff" or not does not matter after that, it's not
"a C struct" any more.

V
 
I

Ian Collins

JohnQ said:
I was pondering the technique of restricting default constructor, copy
constructor, assignment operator though and its validity for structs as
well as classes:
Why should the validity be any different?

As a hangover form C it is idiomatic in C++ to use an unadorned struct
as bucket of data.
struct B
{
B(); // disallow def construction
B(const B&); // disallow copy construction
const B& operator=(const B&); // disallow assignment

int data_member; // public by default

B(int arg)
: data_member(arg) {}
};

If I disallow the stuff in struct B, it acts less like a C struct, yes?
Well it's obvious that it does.
 
J

JohnQ

Gavin Deane said:
Perhaps, but it's not defined in C++. Of more direct relevance to the
OP though is that, regardless of whether we're all happy with that
definition of "bitwise copy", it's not what happens in the implicitly-
defined copy constructor, which does a memberwise copy.

That's interesting. Apparently "a struct is a struct" hardly ever! Oh wait,
does C do memberwise copy of structs also or bitwise?

John
 
V

Victor Bazarov

JohnQ said:
Different from an identical class?

What's "an identical class"? A class with the same order of its
members, all declared public? No difference.
Conceptually how?

Conceptually, every type has a destructor (or you can say that it
does, since you can call it). The standard has s concept of
"a pseudo-destructor call", which means that any type has at least
a pseudo-destructor. In my book you can say that a concept of
a destructor exists for every type. There is no code where the
CPU is led to perform some actions when an object of a POD type is
disposed of, yes. In that sense, a POD type does not have a d-tor.
So, conceptually, yes, physically, no.
Lately, I've been pondering, "when does a struct stop being a
struct?". To me, that's when its not the same size as a C struct or
not layed out the same. So obviously, when a virtual function gets
added, then "a struct stops being a struct". I think I can add
non-virtual member functions, non-virtual destructor and operators ad
infinitum and the "struct will still be a struct" (right?).

Nope. If we agree to substitute the words "C struct" with "POD",
then the Standard says that as soon as you add a user-defined c-tor,
it's not a POD any more, so not all non-virtual member functions
are "harmless" as far as POD-ness is concerned.
Even
though some explicit syntax would make things more evident:

struct A
{
int data;
};

struct B
{
int data;

B(int val){ data = val; } // OK, not virtual
};

Here, 'B' is not a POD class.
class StructWrapper
{
A a_struct;

public:
A(int val){ a_struct.data = val; }

You mean

StructWrapper(int val) { a_struct.data = val; }

, right?
operator A&(){ return a_struct; }
};

Where struct B can be used identically to struct A or StructWrapper (I
hope!) as the layouts and sizes are the same (assume the operator is
being used for StructWrapper when I say "can be used identically").

Nothing in the Standard says what the layouts are. We cannot rely on
their being the same.
sizeof(A)==sizeof(B)==sizeof(StructWrapper)

That doesn't matter.
But a_struct in StructWrapper would have to be made public to
guarantee the same layout as A and B?

Again, there is no way to "guarantee" what's not defined. There is
no definition of a complete class layout in the Standard.
The equivalent of doing a memcpy of the class or struct (whether I
used the right terminology or not I don't know... "bytewise" seems
more appropriate).

Well, calling 'memcpy' upon copy-constructing an object is up to the
implementation. There is no way to know exactly what they do with
POD, most likely 'memcpy', or 'memmove', or some such. However, it
would be safer to assume that "memberwise copy" is performed, which
means that copy semantics for each member (provided they exist) are
invoked.
OK, so from what I gather, the compiler may or may not generate the
functions/operators depending on the data members. Is it that if
there is any non-POD data member, then the functions/operators get
generated? Is it always the full set (?): default constructor, copy
constructor, assignment operator, (destructor?).

No, not always. For example, it's possible to copy-construct
a reference, but it's not possible to assign one, so if your class
has a data member that is a reference (it does make it non-POD, BTW),
then the copy c-tor can (and will) be generated but the copy
assignment op cannot (and will not) be.

V
 

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,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top