From: Cary on 2 Aug 2010 22:18 On 8月3日, 上午6時01分, PGK <graham.k...(a)gmail.com> wrote: > Hi all, > > Why is it that an object can be initialised by itself without error? > What is the purpose of such leniency? For example: > > Foo a(a); // No compile error > > Cheers, > > The output of the subsequent code is: > > Out 1: 7 > In 1 : -1149044056 > In 2 : -1149044056 > Out 2: 7 > > -------------------------------------- > > #include <iostream> > > struct Foo { > Foo(int x) { m_x = x; } > Foo(Foo &f) { m_x = f.m_x; } > int m_x; > > }; > > int main(int argc, char *argv[]) > { > Foo a(7); > std::cout << "Out 1: " << a.m_x << std::endl; > { > Foo a(a); > std::cout << "In 1 : " << a.m_x << std::endl; > Foo b(b); > std::cout << "In 2 : " << a.m_x << std::endl; > } > std::cout << "Out 2: " << a.m_x << std::endl; > > return 0; > > } > In my opinion, this is a well-formed but undefined behavior. you say "Foo a(a);" you declare the "a" previously, so you can pass it to self initialize. but when calling its copy constructor, you use its own indeterminate value to initialize itself... mostly if there is a memory management in Foo class, you will got a seg fault. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Lailoken on 2 Aug 2010 22:18 On Aug 2, 3:01 pm, PGK <graham.k...(a)gmail.com> wrote: > Hi all, > > Why is it that an object can be initialised by itself without error? > What is the purpose of such leniency? For example: > > Foo a(a); // No compile error Because it happens in two distinct parts. Firstly the memory for the object gets allocated (and the vtbl gets set up), and thus 'a' is allocated but uninitialized. Then the object (which still does not have any constructors called) is passed to its own constructor. For one thing it may or may not be useful when doing certain types of object pooling, although I cannot think of a good use at the moment. (And object pooling is best done by creating class local new and delete operators) But it all seems pretty legal to me at first glance. Hope this helps. > Cheers, > > The output of the subsequent code is: > > Out 1: 7 > In 1 : -1149044056 > In 2 : -1149044056 > Out 2: 7 > > -------------------------------------- > > #include <iostream> > > struct Foo { > Foo(int x) { m_x = x; } > Foo(Foo &f) { m_x = f.m_x; } > int m_x; > > }; > > int main(int argc, char *argv[]) > { > Foo a(7); > std::cout << "Out 1: " << a.m_x << std::endl; > { > Foo a(a); This 'a' is initialized with itself, not by the one above. Thus the constructor basically does nothing. > std::cout << "In 1 : " << a.m_x << std::endl; > Foo b(b); > std::cout << "In 2 : " << a.m_x << std::endl; > } > std::cout << "Out 2: " << a.m_x << std::endl; > return 0; > } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: PGK on 3 Aug 2010 07:19 > Interestingly and confusingly enough, [3.3.1] also gives examples > which seem contradictory at first: > > const int i = 2; > { int i[i]; } // declares a local of two integers > > const int x = 12; > { enum { x = x }; } // x is initialized with 12 Yes, the first one seems very like my own example, but the "outer" i is used instead. I also find it odd that the block construct will allow usage up until a new declaration: Foo a(7); { std::cout << a.m_x << std::endl; // The outer a Foo a(8); std::cout << a.m_x << std::endl; // The inner a } produces: 7 8 -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Francis Glassborow on 3 Aug 2010 13:30 PGK wrote: >> Interestingly and confusingly enough, [3.3.1] also gives examples >> which seem contradictory at first: >> >> const int i = 2; >> { int i[i]; } // declares a local of two integers >> >> const int x = 12; >> { enum { x = x }; } // x is initialized with 12 > > Yes, the first one seems very like my own example, but > the "outer" i is used instead. I also find it odd that > the block construct will allow usage up until a new declaration: Well that is a basic principle for C++ (that comes from C) names only enter scope when they are declared and code is interpreted simply on what has been seen so far. There is an exception to this and that is where you define a function in a class definition. The definition is always treated s if it was after the completion of the class definition. Now back to your question. I raised this issue in the mid 90s and proposed that the such declarations be ill-formed. Unfortunately there was already some rather bizarre code that made constructive use of the facility (for user defined types). No I do not fully understand how they were using it because it includes hi-jacking the copy ctor but it was nonetheless in existence and therefore WG21 voted down my proposal (rightly IMO) but good tools such as PCLINT++ will raise a warning. What concerns me more than a little is the examples quoted from 3.3.1 as I think that just adds confusion without any gain. I would hope that good tools raise warnings for both those as they really are terrible code. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: Foo a(a); // ? Next: Template type deduction failure when using reference types |