c_str from anonymous std::string

Discussion in 'C++' started by Andrew Tomazos, Dec 12, 2011.

  1. class X
    {
    operator std::string(); // stringify X instance
    };

    void f(const char*);

    X x = ...
    f(string(x).c_str());

    According to the C++11 standard, will the destructor of std::string be
    called before or after the call to f, or is it undefined?

    Thanks,
    Andrew.
    Andrew Tomazos, Dec 12, 2011
    #1
    1. Advertising

  2. Andrew Tomazos

    SG Guest

    On Dec 12, 8:57 am, Andrew Tomazos wrote:
    > class X
    > {
    >     operator std::string(); // stringify X instance
    > };
    >
    > void f(const char*);
    >
    > X x = ...
    > f(string(x).c_str());
    >
    > According to the C++11 standard, will the destructor of std::string be
    > called before or after the call to f, or is it undefined?


    After. The code is fine.

    Cheers!
    SG
    SG, Dec 12, 2011
    #2
    1. Advertising

  3. Andrew Tomazos

    Goran Guest

    On Dec 12, 8:57 am, Andrew Tomazos <> wrote:
    > class X
    > {
    >     operator std::string(); // stringify X instance
    >
    > };
    >
    > void f(const char*);
    >
    > X x = ...
    > f(string(x).c_str());
    >
    > According to the C++11 standard, will the destructor of std::string be
    > called before or after the call to f, or is it undefined?


    My understanding is that such temporaries is destroyed when statement
    is finished, which, here, is after the semicolon.

    Goran.
    Goran, Dec 12, 2011
    #3
  4. Andrew Tomazos

    MikeWhy Guest

    Goran wrote:
    > On Dec 12, 8:57 am, Andrew Tomazos <> wrote:
    >> class X
    >> {
    >> operator std::string(); // stringify X instance
    >>
    >> };
    >>
    >> void f(const char*);
    >>
    >> X x = ...
    >> f(string(x).c_str());
    >>
    >> According to the C++11 standard, will the destructor of std::string
    >> be called before or after the call to f, or is it undefined?

    >
    > My understanding is that such temporaries is destroyed when statement
    > is finished, which, here, is after the semicolon.


    It should be further noted that "string(x)" here is an explicit C-style
    typecast, syntactically identical to "((std::string)x)", followed by copy
    construction of std::string, creating not just one, but *two* temporary
    std::string. What a nasty bit of business. This isn't real code, is it? Just
    some contrived nastiness to astonish and dismay job applicants?
    MikeWhy, Dec 12, 2011
    #4
  5. "MikeWhy" <> wrote:
    > It should be further noted that "string(x)" here is an explicit C-style
    > typecast, syntactically identical to "((std::string)x)", followed by copy
    > construction of std::string, creating not just one, but *two* temporary
    > std::string. What a nasty bit of business. This isn't real code, is it?
    > Just some contrived nastiness to astonish and dismay job applicants?


    Really? Why is operator std::string /followed/ by a copy constuctor? There
    is a copy /on returning/ a std::string from the operator function but this
    is an inherent "problem" of returning by value and not the fault of the
    rest of the code ("problem" in quotes, because this is optimized away by
    most compilers).

    Or am I misunderstanding something obvious?

    Tobi
    Tobias Müller, Dec 13, 2011
    #5
  6. MikeWhy <> wrote:
    > It should be further noted that "string(x)" here is an explicit C-style
    > typecast, syntactically identical to "((std::string)x)"


    It looks like a regular object instantiation by calling its constructor
    to me. (The latter is also interpreted like that.)

    How else would you construct a temporary object?
    Juha Nieminen, Dec 13, 2011
    #6
  7. Andrew Tomazos

    Ian Collins Guest

    On 12/13/11 12:39 PM, MikeWhy wrote:
    >
    > It should be further noted that "string(x)" here is an explicit C-style
    > typecast, syntactically identical to "((std::string)x)", followed by copy
    > construction of std::string, creating not just one, but *two* temporary
    > std::string.


    In addition to the other corrections, there really isn't such a thing as
    an "explicit C-style typecast". There is a C style cast (witch is
    always explicit) and there's a type conversion (which is isn't).

    --
    Ian Collins
    Ian Collins, Dec 13, 2011
    #7
  8. On Dec 13, 12:39 am, "MikeWhy" <> wrote:
    > Goran wrote:
    > > On Dec 12, 8:57 am, Andrew Tomazos <> wrote:
    > >> class X
    > >> {
    > >> operator std::string(); // stringify X instance

    >
    > >> };

    >
    > >> void f(const char*);

    >
    > >> X x = ...
    > >> f(string(x).c_str());

    >
    > >> According to the C++11 standard, will the destructor of std::string
    > >> be called before or after the call to f, or is it undefined?

    >
    > > My understanding is that such temporaries is destroyed when statement
    > > is finished, which, here, is after the semicolon.

    >
    > It should be further noted that "string(x)" here is an explicit C-style
    > typecast, syntactically identical to "((std::string)x)", followed by copy
    > construction of std::string, creating not just one, but *two* temporary
    > std::string.


    $ cat < test.cpp

    #include <iostream>

    using namespace std;

    class A
    {
    public:
    A() { cout << "d"; }
    A(const A& a) : x(a.x) { cout << "c"; }

    int getx() const { return x; }
    int x;
    };

    class B
    {
    public:
    B(int i) : x(i) {}
    operator A() { A a; a.x = x; return a; }

    int x;
    };

    void f(int x) { cout << x << endl; }

    int main(int argc, char** argv)
    {
    B b(argc);

    f(A(b).getx());
    }

    $ g++ test.cpp
    $ ./a.out
    d1

    I only count one d. :)

    Due to the return value optimization...
    <http://en.wikipedia.org/wiki/Return_value_optimization>

    > What a nasty bit of business. This isn't real code, is it? Just
    > some contrived nastiness to astonish and dismay job applicants?


    Imagine how much less embarrassed you would be if you stated it this
    way:

    "I think that two temporaries will be created, won't they?"

    and left it at that. ;)

    Enjoy,
    Andrew.
    Andrew Tomazos, Dec 13, 2011
    #8
  9. Andrew Tomazos

    MikeWhy Guest

    Andrew Tomazos wrote:
    > On Dec 13, 12:39 am, "MikeWhy" <> wrote:
    >> Goran wrote:
    >>> On Dec 12, 8:57 am, Andrew Tomazos <> wrote:
    >>>> class X
    >>>> {
    >>>> operator std::string(); // stringify X instance

    >>
    >>>> };

    >>
    >>>> void f(const char*);

    >>
    >>>> X x = ...
    >>>> f(string(x).c_str());

    >>
    >>>> According to the C++11 standard, will the destructor of std::string
    >>>> be called before or after the call to f, or is it undefined?

    >>
    >>> My understanding is that such temporaries is destroyed when
    >>> statement is finished, which, here, is after the semicolon.

    >>
    >> It should be further noted that "string(x)" here is an explicit
    >> C-style typecast, syntactically identical to "((std::string)x)",
    >> followed by copy construction of std::string, creating not just one,
    >> but *two* temporary std::string.

    >
    > $ cat < test.cpp
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > class A
    > {
    > public:
    > A() { cout << "d"; }
    > A(const A& a) : x(a.x) { cout << "c"; }
    >
    > int getx() const { return x; }
    > int x;
    > };
    >
    > class B
    > {
    > public:
    > B(int i) : x(i) {}
    > operator A() { A a; a.x = x; return a; }
    >
    > int x;
    > };
    >
    > void f(int x) { cout << x << endl; }
    >
    > int main(int argc, char** argv)
    > {
    > B b(argc);
    >
    > f(A(b).getx());
    > }
    >
    > $ g++ test.cpp
    > $ ./a.out
    > d1
    >
    > I only count one d. :)
    >
    > Due to the return value optimization...
    > <http://en.wikipedia.org/wiki/Return_value_optimization>
    >
    >> What a nasty bit of business. This isn't real code, is it? Just
    >> some contrived nastiness to astonish and dismay job applicants?

    >
    > Imagine how much less embarrassed you would be if you stated it this
    > way:
    >
    > "I think that two temporaries will be created, won't they?"
    >
    > and left it at that. ;)
    >
    > Enjoy,
    > Andrew.


    Cause for my embarrassment is wholly imaginary.

    The following produced:

    [[
    Boo::eek:perator ZooString()const
    ZooString<0013FF48>::ZooString(const char *) {Boo}
    ZooString<0013FF2C>::ZooString(const ZooString &) {Boo}
    Boo
    ]]

    Note the copy construction.



    //================================
    //================================
    #include <iostream>
    #include <string>

    //================================
    //================================
    class ZooString
    {
    public:
    ZooString(const char * s = "")
    : str(s)
    { PrintTo(std::cout, "::ZooString(const char *)") << '\n';
    }

    ZooString(const ZooString & r)
    : str(r.str)
    { PrintTo(std::cout, "::ZooString(const ZooString &)") << '\n';
    }

    const char * c_str() const
    {
    return str.c_str();
    }

    std::eek:stream & PrintTo(std::eek:stream & os, const char * msg) const
    {
    os << "ZooString<" << (void*)this << '>' << msg
    << " {" << str << '}';
    return os;
    }
    private:
    std::string str;
    };
    //================================
    //================================
    class Boo
    {
    public:
    Boo(){}
    Boo(const Boo &);
    operator ZooString() const
    { std::cout << "Boo::eek:perator ZooString()const\n";
    return "Boo";
    }
    };
    //================================
    //================================
    int main(int, char**)
    {
    Boo hoo;
    std::cout << ZooString(hoo).c_str() << '\n';

    return 0;
    }
    MikeWhy, Dec 13, 2011
    #9
  10. On Dec 13, 6:10 pm, "MikeWhy" <> wrote:
    > Andrew Tomazos wrote:
    > > On Dec 13, 12:39 am, "MikeWhy" <> wrote:
    > >> Goran wrote:
    > >>> On Dec 12, 8:57 am, Andrew Tomazos <> wrote:
    > >>>> class X
    > >>>> {
    > >>>> operator std::string(); // stringify X instance

    >
    > >>>> };

    >
    > >>>> void f(const char*);

    >
    > >>>> X x = ...
    > >>>> f(string(x).c_str());

    >
    > >>>> According to the C++11 standard, will the destructor of std::string
    > >>>> be called before or after the call to f, or is it undefined?

    >
    > >>> My understanding is that such temporaries is destroyed when
    > >>> statement is finished, which, here, is after the semicolon.

    >
    > >> It should be further noted that "string(x)" here is an explicit
    > >> C-style typecast, syntactically identical to "((std::string)x)",
    > >> followed by copy construction of std::string, creating not just one,
    > >> but *two* temporary std::string.

    >
    > > $ cat < test.cpp

    >
    > > #include <iostream>

    >
    > > using namespace std;

    >
    > > class A
    > > {
    > > public:
    > > A() { cout << "d"; }
    > > A(const A& a) : x(a.x) { cout << "c"; }

    >
    > > int getx() const { return x; }
    > > int x;
    > > };

    >
    > > class B
    > > {
    > > public:
    > > B(int i) : x(i) {}
    > > operator A() { A a; a.x = x; return a; }

    >
    > > int x;
    > > };

    >
    > > void f(int x) { cout << x << endl; }

    >
    > > int main(int argc, char** argv)
    > > {
    > > B b(argc);

    >
    > > f(A(b).getx());
    > > }

    >
    > > $ g++ test.cpp
    > > $ ./a.out
    > > d1

    >
    > > I only count one d. :)

    >
    > > Due to the return value optimization...
    > > <http://en.wikipedia.org/wiki/Return_value_optimization>

    >
    > >> What a nasty bit of business. This isn't real code, is it? Just
    > >> some contrived nastiness to astonish and dismay job applicants?

    >
    > > Imagine how much less embarrassed you would be if you stated it this
    > > way:

    >
    > >     "I think that two temporaries will be created, won't they?"

    >
    > > and left it at that. ;)

    >
    > > Enjoy,
    > >     Andrew.

    >
    > Cause for my embarrassment is wholly imaginary.
    >
    > The following produced:
    >
    > [[
    > Boo::eek:perator ZooString()const
    > ZooString<0013FF48>::ZooString(const char *) {Boo}
    > ZooString<0013FF2C>::ZooString(const ZooString &) {Boo}
    > Boo
    > ]]
    >
    > Note the copy construction.


    So get a real compiler...

    $ g++ YourExample.cpp
    $ ./a.out
    Boo::eek:perator ZooString()const
    ZooString<0x7fff335e93e0>::ZooString(const char *) {Boo}
    Boo

    $ g++ --version
    g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

    Regards,
    Andrew.
    Andrew Tomazos, Dec 13, 2011
    #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. Christopher Benson-Manica

    std::string c_str()

    Christopher Benson-Manica, Feb 17, 2004, in forum: C++
    Replies:
    1
    Views:
    2,957
    Gianni Mariani
    Feb 17, 2004
  2. Vyacheslav Kononenko

    What storage does std::string::c_str() use?

    Vyacheslav Kononenko, Sep 8, 2004, in forum: C++
    Replies:
    2
    Views:
    3,605
    Old Wolf
    Sep 9, 2004
  3. Replies:
    3
    Views:
    2,130
    Vyacheslav Kononenko
    Sep 9, 2004
  4. DaVinci
    Replies:
    3
    Views:
    419
    Jacek Dziedzic
    Apr 9, 2006
  5. DaVinci
    Replies:
    7
    Views:
    711
    Fraser Ross
    Apr 7, 2006
Loading...

Share This Page