constructor problem

C

campos

Here are my codes:

#include <iostream>

using namespace std;

class Test
{
public:
Test() { cout << "Test()" << endl; }
Test(const string& s) { str = s; cout<< "Test(string)" << endl; }
Test(const Test& t) { str = s; cout << "Test(const Test&)" << endl;
}
private:
string str;
}

int main()
{
string str("hello");
Test t1(str);
Test t2 = str;
return 0;
}

I use VC++ 7.0 to compile and run the program, the result is:
-----------------
Test(string)
Test(string)
-----------------

copy constructor has not been called.


But in "C++ Primer 4th Edition", Ch 13.1
-----------------------------------------------------------
Usually the difference between direct- or copy-initialization is at
most a matter of low-level optimization. However, for types that do not
support copying, or when using a constructor that is nonexplicit
(Section 12.4.4, p. 462) the distinction can be essential:

ifstream file1("filename"); // ok: direct initialization
ifstream file2 = "filename"; // error: copy constructor is private
// This initialization is okay only if
// the Sales_item(const string&) constructor is not explicit
Sales_item item = string("9-999-99999-9");
 
S

Salt_Peter

campos said:
Here are my codes:

#include <iostream>
#include <ostream>
#include said:
using namespace std;

class Test
{
public:
Test() { cout << "Test()" << endl; }

always, always initialize all your members.

Test() : str() { std::cout << "default Test()" << std::endl; }
Test(const string& s) { str = s; cout<< "Test(string)" << endl; }

The above should be:
Test(const std::string& s) : str(s) { std::cout<<
"Test(string)" << std::endl; }
Which by the way, is a conversion ctor.
Test(const Test& t) { str = s; cout << "Test(const Test&)" << endl;
}
private:
string str;
}

; // semicolon required
int main()
{
string str("hello");
Test t1(str);
Test t2 = str; // invoking conversion ctor
return 0;
}

I use VC++ 7.0 to compile and run the program, the result is:

There was no copy.
But in "C++ Primer 4th Edition", Ch 13.1
-----------------------------------------------------------
Usually the difference between direct- or copy-initialization is at
most a matter of low-level optimization. However, for types that do not
support copying, or when using a constructor that is nonexplicit
(Section 12.4.4, p. 462) the distinction can be essential:

ifstream file1("filename"); // ok: direct initialization
ifstream file2 = "filename"; // error: copy constructor is private
// This initialization is okay only if
// the Sales_item(const string&) constructor is not explicit
Sales_item item = string("9-999-99999-9");
-----------------------------------------------------------

However, even if I declare the copy constructor of Test class as
private, still it can be compiled and executed correctly. That seems
the following sentences are treated as the same:

Try:
Test t2 = t1; // thats a copy since t1 and t2 are of the same type
t1 = t2; // thats now an assignment
 
S

Squeamizh

Salt_Peter said:
always, always initialize all your members.

Test() : str() { std::cout << "default Test()" << std::endl; }

Why? You're just default constructing the std::string, anyway.
 
J

John Carson

campos said:
Here are my codes:

#include <iostream>

using namespace std;

class Test
{
public:
Test() { cout << "Test()" << endl; }
Test(const string& s) { str = s; cout<< "Test(string)" << endl; }
Test(const Test& t) { str = s; cout << "Test(const Test&)" << endl;
}
private:
string str;
}

int main()
{
string str("hello");
Test t1(str);
Test t2 = str;
return 0;
}

I use VC++ 7.0 to compile and run the program, the result is:

This is permissible as an optimization. However, according to the Standard,
the copy constructor is required to be accessible even if not used in this
scenario. Comeau online refuses to compile the code when the copy
constructor is private. VC++ 2005 also refuses to compile it if language
extensions is disabled (/Za switch).
 
V

Venkatesh

Ctors are implicit by default..which means this statement
Test t2 = str; is no different from Test t2 (str);

Make the 2nd ctor as explicit
explicit Test(const string& s))
if you want to avoid an assignment to call a non copy ctor.

-
Venkatesh
 
J

John Carson

Venkatesh said:
Ctors are implicit by default..which means this statement
Test t2 = str; is no different from Test t2 (str);

Incorrect. Implicit constructors means that

Test t2 = str;

is no different from

Test t2 = Test(str);

Subject to the qualification below, both of these involve a constructor call
to create a Test temporary from str, and a copy constructor to copy this
Test temporary to t2. Both are different from

Test t2(str);

which does not involve a copy constructor. See section 12.6 of the Standard.

By section 12.8/15 of the standard, it is possible with both

Test t2 = str;

and

Test t2 = Test(str);

to omit the copy constructor call as an optimization.
Make the 2nd ctor as explicit
explicit Test(const string& s))
if you want to avoid an assignment to call a non copy ctor.

That will mean that

Test t2 = str;

doesn't compile. However

Test t2 = Test(str);

will compile and copy construction may be omitted as an optimization.
 
V

Venkatesh

John said:
Incorrect. Implicit constructors means that

Test t2 = str;

is no different from

Test t2 = Test(str);

Subject to the qualification below, both of these involve a constructor call
to create a Test temporary from str, and a copy constructor to copy this
Test temporary to t2. Both are different from

Test t2(str);

which does not involve a copy constructor. See section 12.6 of the Standard.

By section 12.8/15 of the standard, it is possible with both

Test t2 = str;

and

Test t2 = Test(str);

to omit the copy constructor call as an optimization.

May be, i should have elaborated a bit more.
AFAIK, if something happens to go through an implicit ctor, then copy
ctor will not be called which means
Test t2 = str; is no different from Test t2 (str);
where as Test t2 = Test(str) may skip or go through the copy ctor.

Also a closer look at the creation of these two objects will tell the
fact that calls made for 'Test t2 = str' are exaclty the same as 'Test
t2(str)'

Please refer Bjarne's TCPL section 11.3.4 where reads like complex x=2
is equivalent to complex x(2) and also that complex y = complex(2,0) is
equivalent to complex y(2, 0);
That will mean that

Test t2 = str;

doesn't compile. However

Test t2 = Test(str);

will compile and copy construction may be omitted as an optimization.

I can't help in this regard as the call to the ctor Test(const string&
s) is made explicit which is not required here.

-
Venkatesh
 
J

John Carson

Venkatesh said:
May be, i should have elaborated a bit more.
AFAIK, if something happens to go through an implicit ctor, then copy
ctor will not be called which means
Test t2 = str; is no different from Test t2 (str);
where as Test t2 = Test(str) may skip or go through the copy ctor.

This is just plain wrong. As I have already stated,

Test t2 = str;
and
Test t2 = Test(str);

are the same when there is an implicit constructor. In either case the copy
constructor may or may not be called. In *both* cases, the copy constructor
is required to be accessible even if not called.

With

Test t2 (str);

by contrast, the copy constructor is *never* called and is not required to
be accessible.
Also a closer look at the creation of these two objects will tell the
fact that calls made for 'Test t2 = str' are exaclty the same as 'Test
t2(str)'

Wrong. Compile them using Comeau online with a private copy constructor.

http://www.comeaucomputing.com/tryitout/

Observe that

Test t2 (str);

will compile but

Test t2 = str;

will *not* compile.
Please refer Bjarne's TCPL section 11.3.4 where reads like complex x=2
is equivalent to complex x(2) and also that complex y = complex(2,0)
is equivalent to complex y(2, 0);

You are misreading this. Start in the previous section (p. 270), where he
says that

complex b = 3;

means

complex b = complex(3);

Then in section 11.3.4, he says that:

"In principle, copy constructors are used in simple initializations such as:

complex x = 2;
complex y = complex(2,0);"

Such initializations are therefore NOT equivalent to

complex y(2,0);

because it is NOT the case that "in principle, copy constructors are used"
in such initializations.

He also comments that: "It is possible to restrict the set of values
accepted by the = style of initialization compared to the () style by making
the copy constructor private", i.e., inaccessible, which is the point I have
made above.
 

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

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top