| | |
Const Question - Why is this happening?
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
•
•
Join Date: Jan 2008
Posts: 3,810
Reputation:
Solved Threads: 501
I've been experimenting around with the
I have the
My question is: why was the non-const copy constructor called rather than the const copy constructor, given the word
const modifier, trying to make sure I understand it and clearly I do not. I wrote this program. Note line 28, where I am changing the value of the parameter passed to a copy constructor, and the word const on line 40: C++ Syntax (Toggle Plain Text)
#include <iostream> using namespace std; class MyClass { public: int x; MyClass (int i) { x = i; cout << "In int constructor. x = " << x << endl; } MyClass (const MyClass& f) { cout << "In const copy constructor: f.x = " << f.x << endl; x = f.x; } MyClass (MyClass& f) { cout << "In non-const copy constructor pre-mutation: f.x = " << f.x << endl; x = f.x; f.x = 8; cout << "In non-const copy constructor post-mutation: f.x = " << f.x << endl; } ~MyClass () { cout << "In destructor: x = " << x << endl; } }; void Func (const MyClass f) { cout << "Inside Func: f.x = " << f.x << endl; } int main () { MyClass f(4); cout << "In main before Func call: f.x = " << f.x << endl; Func (f); cout << "In main after Func call: f.x = " << f.x << endl; return 0; }
I have the
const modifier on line 40, which I believed made it so f could not be changed and thus I believed would require a call to a copy constructor that couldn't change the parameter passed to it. I wrote a copy constructor that was allowed to change its parameter passed to it and one that wasn't allowed to, using the const keyword. Here's the output. C++ Syntax (Toggle Plain Text)
In int constructor. x = 4 In main before Func call: f.x = 4 In non-const copy constructor pre-mutation: f.x = 4 In non-const copy constructor post-mutation: f.x = 8 Inside Func: f.x = 4 In destructor: x = 4 In main after Func call: f.x = 8 In destructor: x = 8
My question is: why was the non-const copy constructor called rather than the const copy constructor, given the word
const on line 40? Thank you. This is actually very interesting. Well, first thing, i managed to call const constructor by doing this to main:
So, if u pass const object to Func, it will obviously trigger const constructor.
I'll post if i find out something new
C++ Syntax (Toggle Plain Text)
int main () { const MyClass f(4); cout << "In main before Func call: f.x = " << f.x << endl; Func (f); cout << "In main after Func call: f.x = " << f.x << endl; cin.get(); return 0; }
So, if u pass const object to Func, it will obviously trigger const constructor.
I'll post if i find out something new
Ok, I have an idea, but am not sure 100%.
When you write:
You say to compiler: MyClass g (I changed a name from f, but it's irrelevant) will not change!
But, that const keyword is irrelevant of calling constructor.
When you write:
You say to compiler: This constructor is going to GET object of type: const MyClass!
When you write inside a main function:
When you write:
C++ Syntax (Toggle Plain Text)
void Func (const MyClass g)
But, that const keyword is irrelevant of calling constructor.
When you write:
C++ Syntax (Toggle Plain Text)
MyClass (const MyClass& f)
When you write inside a main function:
C++ Syntax (Toggle Plain Text)
MyClass a(3); const MyClass b(a); MyClass c(a); Func(3); //you are calling int constructor that will create const MyClass g(3) Func(b); //you are calling const constructor, that will create const MyClass g(b) because b is const Func(c); //you are calling non-const constructor that will create const MyClass g(c) because c is non-const!
•
•
Join Date: Jan 2008
Posts: 3,810
Reputation:
Solved Threads: 501
I think you are on to something here, though I'm still puzzled. I ran your revised program and it made the calls to the constructors you predicted it would. Is there something different about calling the copy constructor as opposed to another member function? For example, if I add this member function:
and change my non-member function to this:
I get errors on both lines because of the
Note that the argument received by the copy constructor is the same as that received by the function
void MyClass::DoSomething (MyClass& f)
{
}and change my non-member function to this:
C++ Syntax (Toggle Plain Text)
void MyClass Func (const MyClass f) { f.x = 10; f.DoSomething (f); }
I get errors on both lines because of the
const stipulation, which is what I expected. I have to write function Func in a way that f can't be changed. But it IS changed when the function calls the non-const copy constructor. MyClass (MyClass& f)
{
cout << "In non-const copy constructor pre-mutation: f.x = "
<< f.x << endl;
x = f.x;
f.x = 8;
cout << "In non-const copy constructor post-mutation: f.x = "
<< f.x << endl;
}Note that the argument received by the copy constructor is the same as that received by the function
DoSomething . The compiler doesn't allow DoSomething to be called because of the lack of the const modifier, but the call to the copy constructor is acceptable. So there must be some difference between a constructor and a regular old member function that allows this, but I don't know what it is. I don't see why there should be any difference. When you write:
And let's say we call Func:
What happens? First let's see what happens in a function:
1. We put in a Func "some_other_MyClass_obj".
2. Program calls constructor to construct "f", a local object inside Func
3. Constructor is checking what are you giving to him. He is checking if "some_other_MyClass_obj" is of type const MyClass or simply MyClass, and then calls proper constructor function.
He doesn't care about line "const MyClass f", because after the "f" is constructed, it will be given const-ness.
4. f is made, and is given his const-ness.
OK, what happens in your recent functions, I'll try to explain.
You have a member function doSomething. That function takes MyClass as argument, and it can change it.
Of course you get error when you try to change f inside your non-member function, that's because f is const! But the important thing is that the const-ness is given AFTER constructor (it's obvious, because constructor HAS to change object!)
And the only thing that distincts your two constructors (for post before) is that one accepts one type of argument, and the other one accepts other type of argument.
C++ Syntax (Toggle Plain Text)
void MyClass Func (const MyClass f) //or even simply: const MyClass f(some_MyClass_obj);
C++ Syntax (Toggle Plain Text)
Func(some_other_MyClass_obj);
1. We put in a Func "some_other_MyClass_obj".
2. Program calls constructor to construct "f", a local object inside Func
3. Constructor is checking what are you giving to him. He is checking if "some_other_MyClass_obj" is of type const MyClass or simply MyClass, and then calls proper constructor function.
He doesn't care about line "const MyClass f", because after the "f" is constructed, it will be given const-ness.
4. f is made, and is given his const-ness.
OK, what happens in your recent functions, I'll try to explain.
You have a member function doSomething. That function takes MyClass as argument, and it can change it.
Of course you get error when you try to change f inside your non-member function, that's because f is const! But the important thing is that the const-ness is given AFTER constructor (it's obvious, because constructor HAS to change object!)
And the only thing that distincts your two constructors (for post before) is that one accepts one type of argument, and the other one accepts other type of argument.
•
•
Join Date: Jan 2008
Posts: 3,810
Reputation:
Solved Threads: 501
•
•
•
•
I don't see why there should be any difference. When you write:
And let's say we call Func:C++ Syntax (Toggle Plain Text)
void MyClass Func (const MyClass f) //or even simply: const MyClass f(some_MyClass_obj);
What happens? First let's see what happens in a function:C++ Syntax (Toggle Plain Text)
Func(some_other_MyClass_obj);
1. We put in a Func "some_other_MyClass_obj".
2. Program calls constructor to construct "f", a local object inside Func
3. Constructor is checking what are you giving to him. He is checking if "some_other_MyClass_obj" is of type const MyClass or simply MyClass, and then calls proper constructor function.
He doesn't care about line "const MyClass f", because after the "f" is constructed, it will be given const-ness.
4. f is made, and is given his const-ness.
OK, what happens in your recent functions, I'll try to explain.
You have a member function doSomething. That function takes MyClass as argument, and it can change it.
Of course you get error when you try to change f inside your non-member function, that's because f is const! But the important thing is that the const-ness is given AFTER constructor (it's obvious, because constructor HAS to change object!)
And the only thing that distincts your two constructors (for post before) is that one accepts one type of argument, and the other one accepts other type of argument.
OK. This helps, thank you. I don't imagine anyone would ever actually write a class that, one, had two copy constructors, or two, changed the object being passed to it inside of the copy constructor. This was an exercise in trying to understand how
const worked. My understanding is that you should always write your copy constructor as such: C++ Syntax (Toggle Plain Text)
public MyClass (const MyClass& f) { // code }
and that you'd never write this one:
C++ Syntax (Toggle Plain Text)
public MyClass (MyClass& f) { // code }
This question stems from a question I recently took on a test that basically said, "If you don't write a copy constructor, the compiler will implicitly write a copy constructor for you. What will that copy constructor look like?" I think I answered:
C++ Syntax (Toggle Plain Text)
public MyClass (const MyClass& f) { // code }
as opposed to:
C++ Syntax (Toggle Plain Text)
public MyClass (MyClass& f) { // code }
I wasn't positive that was correct and I'm still not, so I started playing around with the program I first listed to try to figure out this question and some other
const questions. Does anyone know whether I answered correctly? Sci@phy, thanks for the posts. They helped. http://groups.google.com/group/comp....9e5fea271ef312 of any value?
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
•
•
Join Date: Jan 2008
Posts: 3,810
Reputation:
Solved Threads: 501
Thanks. Well it shows an example of a const and non-const constructor, so that's relevant. I'm not using any pointers so deep versus shallow copy is not the issue here I don't think. The discussion seems to be efficiency in that thread rather than the ability to change an object, which is my question, and I didn't see anywhere where that is discussed.
•
•
Join Date: Jan 2008
Posts: 3,810
Reputation:
Solved Threads: 501
OK, I've been researching and the web pages I've visited all seem to say the implicit copy constructor generated by the compiler when you don't create one is:
That is, with the
Wikipedia is usually my final arbiter, so I'll go with them, but if anyone actually knows and can confirm this, I'd definitely appreciate it!
C++ Syntax (Toggle Plain Text)
public MyClass (const MyClass& f) { // code }
That is, with the
const qualifier.Wikipedia is usually my final arbiter, so I'll go with them, but if anyone actually knows and can confirm this, I'd definitely appreciate it!
Thank you all participants for a very interesting discussion in the thread.
Some additions:
Let's remember what is a copy constructor in C++. Copy constructors are (C++ Std, 12.8):
A compiler-generated (default) copy constructor always has const X& parameter. Some careful compilers print warnings if you have more than one copy constructor declared for a class (VC++ 9, for example, does it). I think, it's a very helpful warning in most of cases.
If a class has a copy constructor with X& parameter, this constructor works for non-const initializer (see the 1st post of the thread). It does not matter what "constantness" of initialized object (see an example with Func parameter binding).
So it's possible to modify a non-const only ARGUMENT object (initializer) via X& copy constructor of another object. Sometimes it's useful feature but as usually is an example of bad practice...
At the same time let's repeate that constantness of ordinar (free, not-member) functions parameters is not a part of function signatures. So it's an error to define two functions:
All static member functions are ordinar functions in C++.
Some additions:
Let's remember what is a copy constructor in C++. Copy constructors are (C++ Std, 12.8):
•
•
•
•
A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments
...
Note: all forms of copy constructor may be declared for a class.
If a class has a copy constructor with X& parameter, this constructor works for non-const initializer (see the 1st post of the thread). It does not matter what "constantness" of initialized object (see an example with Func parameter binding).
So it's possible to modify a non-const only ARGUMENT object (initializer) via X& copy constructor of another object. Sometimes it's useful feature but as usually is an example of bad practice...
At the same time let's repeate that constantness of ordinar (free, not-member) functions parameters is not a part of function signatures. So it's an error to define two functions:
C++ Syntax (Toggle Plain Text)
void F(X x) { ... } void F(const X x) { ... }
Last edited by ArkM; Sep 28th, 2008 at 10:08 am.
![]() |
Similar Threads
Other Threads in the C++ Forum
- Previous Thread: Delete or Remove Array Element
- Next Thread: problems with reading random access line from a file
| Thread Tools | Search this Thread |
api array based binary bitmap c++ c/c++ calculator char char* class classes code coding compile console conversion count database delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp iamthwee ifstream input int java lib linkedlist linker linux list loop looping loops map math matrix memory multiple news node number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg sorting string strings temperature template templates test text text-file tree unix url variable vector video visualstudio win32 windows winsock word wordfrequency wxwidgets






