473,385 Members | 1,912 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

initialization of function argument

Suppose we have a class named Test.

Test obj; // assuming default ctor is available
Test direct_init(obj); // direct initialization happens here
Test copy_init = obj; // copy initialization happens here

Suppose we have a function

void fn(Test arg);

When we call fn() with fn(obj), the copy ctor
is called to construct 'arg'. Am I correct?
Question is what kind of initialization - direct
initialization or copy initialization, happens to
construct arg ?
What does the standard say in this regard ?
If copy initialization happens, then if the copy
ctor is 'explicit', then calling fn(obj) will not
compile. Am I correct ?

Kindly explain

Thanks
V.Subramanian
Nov 25 '07 #1
11 2382

<su**************@yahoo.comwrote in message
news:84**********************************@e23g2000 prf.googlegroups.com...
Suppose we have a class named Test.

Test obj; // assuming default ctor is available
Test direct_init(obj); // direct initialization happens here
I'm not sure what you mean by 'direct initialization', but
the above line invokes the copy constructor.
Test copy_init = obj; // copy initialization happens here
This will also invoke the copy constructor.
>
Suppose we have a function

void fn(Test arg);

When we call fn() with fn(obj), the copy ctor
is called to construct 'arg'. Am I correct?
Yes.
Question is what kind of initialization - direct
initialization or copy initialization, happens to
construct arg ?
Copy construction.
What does the standard say in this regard ?
I don't have my copy at hand.
If copy initialization happens, then if the copy
ctor is 'explicit', then calling fn(obj) will not
compile.
Sure it will.
Am I correct ?
No.

However, if the copy constructor is declared explicit,
the line

Test copy_init = obj;

will not compile. (VC++ 2005 says:
class 'Test' : no copy constructor available or
copy constructor is declared 'explicit'

Kindly explain
Run my example below.
#include <iostream>

class Test
{
static int i;

public:
Test()
{
++i;
std::cout << "Obj " << i << " Default constructor\n";
}

Test(const Test& t)
{
++i;
std::cout << "Obj " << i << " Copy constructor\n";
}

Test& operator=(const Test& t)
{
++i;
std::cout << std::cout << "Obj " << i << " Assignment operator\n";
return *this;
}

~Test()

{
std::cout << "Obj " << i << " destructor\n";
--i;
}
};

int Test::i;

void fn(Test arg)
{
}

int main()
{
Test obj;
Test direct_init(obj);
Test copy_init = obj;
std::cout << "Before calling fn\n";
fn(obj);
std::cout << "After fn()\n";
return 0;
}
Output:

Obj 1 Default constructor
Obj 2 Copy constructor
Obj 3 Copy constructor
Before calling fn
Obj 4 Copy constructor
Obj 4 destructor
After fn()
Obj 3 destructor
Obj 2 destructor
Obj 1 destructor

-Mike
Nov 25 '07 #2
On 2007-11-25 17:21, Alf P. Steinbach wrote:
* Mike Wahler:
><su**************@yahoo.comwrote in message
>>>
void fn(Test arg);

When we call fn() with fn(obj), the copy ctor
is called to construct 'arg'. Am I correct?

Yes.
>>Question is what kind of initialization - direct
initialization or copy initialization, happens to
construct arg ?

Copy construction.
>>What does the standard say in this regard ?

I don't have my copy at hand.

See my reply about two hours earlier in this thread. It's often a good
idea to read earlier replies in the thread, before posting.

>>If copy initialization happens, then if the copy
ctor is 'explicit', then calling fn(obj) will not
compile.

Sure it will.

I'm sorry, it will only compile with a broken compiler (e.g. MSVC).

>> Am I correct ?

No.

He is correct.

>However, if the copy constructor is declared explicit,
the line

Test copy_init = obj;

will not compile. (VC++ 2005 says:
class 'Test' : no copy constructor available or
copy constructor is declared 'explicit'

>>Kindly explain

Run my example below.

When I added the word "explicit" to the copy constructor of your
program, and commented out the copy_init declaration,

Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 47: error: class "Test" has no suitable copy
constructor
fn(obj);
^

1 error detected in the compilation of "ComeauTest.c".

g++ also failed to compile, whereas Visual C++ did compile it.
You should check which flags you are using then, I could not get that
past the VC++ compiler.

--
Erik Wikström
Nov 25 '07 #3
su**************@yahoo.com, India wrote:
Test direct_init(obj); // direct initialization happens here
Test copy_init = obj; // copy initialization happens here
Those lines do the exact same thing. The latter is just syntactic
sugar for the former.
Nov 25 '07 #4
Alf P. Steinbach wrote:
struct Foo
{
explicit Foo( Foo const& ) {}
};

void bar( Foo ) {}

int main()
{
bar( Foo() );
}
Does this mean that making the copy constructor of the class explicit
is an effective way of prohibiting objects of that type from being
passed to functions by value?

If this is so, then calling bar() is basically impossible?
Nov 25 '07 #5
On Nov 25, 7:18 pm, Juha Nieminen <nos...@thanks.invalidwrote:
subramanian10...@yahoo.com, India wrote:
Test direct_init(obj); // direct initialization happens here
Test copy_init = obj; // copy initialization happens here
Those lines do the exact same thing. The latter is just syntactic
sugar for the former.
Not if Test is a class type and obj has a type other than Test.
In that case, the first says to construct a Test with obj, the
second to convert obj to a Test, and construct a Test with the
results of the conversion. In the first, there is no
conversion, so constructors marked explicit can be used, but
conversion operators in the source type can't be), and no copy,
so it is legal even if Test doesn't have an accessible copy
constructor. In the second, there is conversion, so
constructors marked explicit cannot be used, but conversion
operators in the source type can be, and copy, so an accessible
copy constructor must be available.

If obj is of type Test, of course, or a class derived from Test
(ignoring any const or volatile qualifiers), then copy
initialization is defined to have the same behavior as direct
initialization. (It's not really clear if the copy constructor
is declared explicit, of course---the standard contradicts
itself in that case, saying elsewhere that the direct
initialization syntax cannot be used if the constructor is
declared explicit.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 26 '07 #6
On Nov 25, 3:14 pm, "subramanian10...@yahoo.com, India"
<subramanian10...@yahoo.comwrote:
Suppose we have a class named Test.
Test obj; // assuming default ctor is available
Test direct_init(obj); // direct initialization happens here
Test copy_init = obj; // copy initialization happens here
Suppose we have a function
void fn(Test arg);
When we call fn() with fn(obj), the copy ctor
is called to construct 'arg'. Am I correct?
Yes.
Question is what kind of initialization - direct
initialization or copy initialization, happens to
construct arg ?
Formally, it's copy initialization. But the standard also says
that if the type of the initialization is the same as, or a
class derived from, the target type, copy initialization behaves
the same as direct initialization. There is only a difference
when conversions are involved.
What does the standard say in this regard ?
Exactly what I just said.
If copy initialization happens, then if the copy
ctor is 'explicit', then calling fn(obj) will not
compile. Am I correct ?
I don't think so, but the original standard is far from clear.
In the section on initialization, it makes it very clear that if
the initialization expression in copy initialization has the
same type as, or a type derived from, the target type, the
semantics are the same as those of direct initialization. In
the section concerning explicit, on the other hand, the latest
draft says that an explicit constructor will only be used "where
the direct-initialization syntax (8.5) or where casts (5.2.9,
5.4) are explicitly used." (Of course, it contradicts this for
explicit default constructors in the very next sentence. But
that doesn't affect the copy constructor.)

The simplest solution is just to never declare the copy
constructor explicit. (Since explicit is designed to prevent
conversions, and the copy constructor doesn't "convert" anything
in the classical sense of the word, the logical decision would
have been for explicit to be ignored on the copy constructor.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 26 '07 #7
On Nov 25, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-11-25 17:21, Alf P. Steinbach wrote:
Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 47: error: class "Test" has no suitable copy
constructor
fn(obj);
^
1 error detected in the compilation of "ComeauTest.c".
g++ also failed to compile, whereas Visual C++ did compile it.
You should check which flags you are using then, I could not get that
past the VC++ compiler.
Also, perhaps, the version. I think that there was some
discussion concerning what was really meant in the standards
committee; the standard does contradict itself on this subject,
and it's quite possible that compiler implementors interpreted
it differently at one time.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 26 '07 #8
On Nov 26, 3:52 pm, "Alf P. Steinbach" <al...@start.nowrote:

Hello Alf P. Steinbach,

I got clarified with your answer in comp.lang.c++ for the same
question. I thank you for that.
But I had sent this question to comp.std.c++ three days
ago. Since I didn't get the question posted in
comp.std.c++, I thought it got rejected by the moderator
in comp.std.c++. So I posted the same question in
comp.lang.c++.

I regret if I caused any inconvenience to you.

Hope this clarifies.

Thanks
V.Subramanian
Nov 27 '07 #9
On Nov 26, 11:52 am, "Alf P. Steinbach" <al...@start.nowrote:
* James Kanze:
[...]
I don't think so, but the original standard is far from clear.
In the section on initialization, it makes it very clear that if
the initialization expression in copy initialization has the
same type as, or a type derived from, the target type, the
semantics are the same as those of direct initialization. In
the section concerning explicit, on the other hand, the latest
draft says that an explicit constructor will only be used "where
the direct-initialization syntax (8.5) or where casts (5.2.9,
5.4) are explicitly used."
This is also the language of the original standard.

It's not a contradiction: "explicit" is a limitation on
allowable syntax for constructor calls, namely that they must
be explicit, and is not concerned with the final semantic
effect of a call.
In other words, §8.5 on initialization refers to the semantic effect,
whereas §12.3.1 on explicit constructors refers to which syntax syntax
is allowed.
That does sound like the most reasonable interpretation. (Of
what is written, not of what should be specified.)
Only in the cases where explicit constructor call syntax is
not available (the only such case I know is passing an
argument by value) does that limit what can be done, the
possible semantics.
There is no such thing as an "explicit constructor call syntax".
Or are you using this as a synonym for "direct-initialization
syntax or casts"?

At any rate, another case would be return values, and I think
some cases involved in exceptions (catching by value, certainly,
but what about the copy which takes place during a throw?).

[...]
The simplest solution is just to never declare the copy
constructor explicit. (Since explicit is designed to prevent
conversions, and the copy constructor doesn't "convert" anything
in the classical sense of the word, the logical decision would
have been for explicit to be ignored on the copy constructor.)

That would introduce another special case (in addition to the default
constructor), and this time on the argument type. Which would either be
inconsistent with effect of -- I'm assuming this is allowed --
template< class T >
explicit MyClass( T const & );
or make this templated non-copy constructor allow different call
/syntax/ dependending on the actual argument /type/.
It's messy.
Yup. More than I realized at first glance. On the other hand,
it would allow the simple rule of always declaring constructors
explicit, without worrying about whether they might be used for
copy or not.

Your template example suggests an even more pernitious example
to me:

class Toto
{
public:
Toto( Toto& other ) ;
template< typename T >
explicit Toto( T const& other ) ;
} ;

void f( Toto ) ;

void
g()
{
Toto t1 ;
Toto const t2 ;
f( t1 ) ; // no problem...
f( t2 ) ; // illegal! even though a copy is passed.
}

Off hand, I'd say that your example with the template is even
more of an argument that something isn't right. That explicit
should probably only have an effect when an implicit conversion
is involved, and should be ignored otherwise. (But I'm not sure
how to express that in standardese.)
I think perhaps the decision to mix construction and
conversion in one common syntax was not optimal,
I think that there's more or less general agreement about this
now. It's a historical issue.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 27 '07 #10
Juha Nieminen wrote:
Alf P. Steinbach wrote:
> struct Foo
{
explicit Foo( Foo const& ) {}
};

void bar( Foo ) {}

int main()
{
bar( Foo() );
}

Does this mean that making the copy constructor of the class explicit
is an effective way of prohibiting objects of that type from being
passed to functions by value?

If this is so, then calling bar() is basically impossible?
Apparently nobody knows.
Nov 27 '07 #11
Juha Nieminen wrote:
Juha Nieminen wrote:
>Alf P. Steinbach wrote:
>> struct Foo
{
explicit Foo( Foo const& ) {}
};

void bar( Foo ) {}

int main()
{
bar( Foo() );
}

Does this mean that making the copy constructor of the class
explicit is an effective way of prohibiting objects of that type
from being passed to functions by value?

If this is so, then calling bar() is basically impossible?

Apparently nobody knows.
I know.

Yes, it is impossible. The absence of the default c-tor in 'Foo'
makes it impossible to create an instance of 'Foo' to begin the
copying process. And it has nothing to do with the fact that the
copy-c-tor is declared 'explicit'.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Nov 27 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: Wolfram Humann | last post by:
Hi, please don't be too harsh if I made stupid errors creating this simple example from my more complex case. Suppose I have a class like this: class BOOK { const string title;
49
by: Luke Meyers | last post by:
Lately I find myself increasingly preferring the practice of going ever-so-slightly out of my way to avoid the use of the form of initialization which uses the '=' symbol, on the grounds that it...
5
by: wkaras | last post by:
I've compiled this code: const int x0 = 10; const int x1 = 20; const int x2 = 30; int x = { x2, x0, x1 }; struct Y {
23
by: Jess | last post by:
Hello, I understand the default-initialization happens if we don't initialize an object explicitly. I think for an object of a class type, the value is determined by the constructor, and for...
2
by: timlyee | last post by:
int *p = new int; auto_ptr<intap1 = p; //will fail on 3 1 auto_ptr<intap1(p); //ok 2 *ap1 = 12; // 3 the first situation has called :...
2
by: subramanian100in | last post by:
Suppose we have a class named Test. We have a function void fn(Test arg); When this function is called, what kind of initialization - direct initialization or copy initialization, happens to...
15
by: akomiakov | last post by:
Is there a technical reason why one can't initialize a cost static non- integral data member in a class?
7
by: krishna | last post by:
What is the need of this syntax for initializing values, isn't this ambiguous to function call? e.g., int func_name(20); this looks like function call (of course not totally as there is no...
7
by: Brentt | last post by:
Hi, I know this is a terribly simple question, but the docs seem to be designed for people who probably find a the answer to this question terribly obvious. But its not at all obvious to me. I...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.