constructor problem

Discussion in 'C++' started by campos, Dec 29, 2006.

  1. campos

    campos Guest

    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");
    -----------------------------------------------------------

    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:
    --------------------
    Test t1(str);
    Test t2 = str;
    --------------------

    Hope sb can help me.
    Thanks in advance!
    campos, Dec 29, 2006
    #1
    1. Advertising

  2. campos

    Salt_Peter Guest

    campos wrote:
    > Here are my codes:
    >
    > #include <iostream>

    #include <ostream>
    #include <string>

    >
    > 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:
    > -----------------
    > Test(string)
    > Test(string)
    > -----------------
    >
    > copy constructor has not been called.


    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:
    > --------------------
    > Test t1(str);
    > Test t2 = str;
    > --------------------


    Try:
    Test t2 = t1; // thats a copy since t1 and t2 are of the same type
    t1 = t2; // thats now an assignment
    Salt_Peter, Dec 29, 2006
    #2
    1. Advertising

  3. campos

    Squeamizh Guest

    Salt_Peter wrote:
    > campos wrote:
    > > class Test
    > > {
    > > public:
    > > Test() { cout << "Test()" << endl; }

    >
    > always, always initialize all your members.
    >
    > Test() : str() { std::cout << "default Test()" << std::endl; }


    Why? You're just default constructing the std::string, anyway.
    Squeamizh, Dec 29, 2006
    #3
  4. campos

    John Carson Guest

    "campos" <> wrote in message
    news:
    > 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.


    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).


    --
    John Carson
    John Carson, Dec 29, 2006
    #4
  5. campos

    Venkatesh Guest

    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
    John Carson wrote:
    > "campos" <> wrote in message
    > news:
    > > 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.

    >
    > 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).
    >
    >
    > --
    > John Carson
    Venkatesh, Dec 29, 2006
    #5
  6. campos

    John Carson Guest

    "Venkatesh" <> wrote in message
    news:
    > 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.

    --
    John Carson
    John Carson, Dec 29, 2006
    #6
  7. campos

    Venkatesh Guest

    John Carson wrote:
    > "Venkatesh" <> wrote in message
    > news:
    > > 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.
    >


    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);

    > > 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.
    >
    > --
    > John Carson


    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
    Venkatesh, Dec 29, 2006
    #7
  8. campos

    John Carson Guest

    "Venkatesh" <> wrote in message
    news:
    > John Carson wrote:
    >> "Venkatesh" <> wrote in message
    >> news:
    >>> 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.
    >>

    >
    > 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.

    --
    John Carson
    John Carson, Dec 29, 2006
    #8
  9. campos

    Mari Guest

    enrich you knowledge by using other source
    http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html
    http://en.wikipedia.org/wiki/Copy_constructor

    br (best regards)

    "campos" <> wrote in message
    news:...
    > 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");
    > -----------------------------------------------------------
    >
    > 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:
    > --------------------
    > Test t1(str);
    > Test t2 = str;
    > --------------------
    >
    > Hope sb can help me.
    > Thanks in advance!
    >
    Mari, Dec 29, 2006
    #9
  10. campos

    campos Guest

    Got it !

    Thanks John~

    "John Carson дµÀ£º
    "
    > "campos" <> wrote in message
    > news:
    > > 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.

    >
    > 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).
    >
    >
    > --
    > John Carson
    campos, Dec 30, 2006
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Giulio
    Replies:
    9
    Views:
    1,041
    Patrick Kowalzick
    Jun 25, 2003
  2. Brett Irving
    Replies:
    3
    Views:
    3,333
    John Harrison
    Jun 29, 2003
  3. lallous
    Replies:
    5
    Views:
    8,816
    David Harmon
    Jan 23, 2004
  4. Aire
    Replies:
    3
    Views:
    463
    Mike Wahler
    Jan 25, 2004
  5. Generic Usenet Account
    Replies:
    10
    Views:
    2,218
Loading...

Share This Page