C++0x rationales? - Page 3


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Page 3 of 3 FirstFirst 123
Results 31 to 45 of 45

Thread: C++0x rationales?

  1. #31
    Join Date
    Feb 2010
    Posts
    19
    Quote Originally Posted by Xarx View Post
    Bjarne,

    > For almost all uses, I prefer unique
    > ownership as represented by unique_ptr.

    You've mentioned an array of unique_ptr as an example in your articles. If this code would be in a library, it would prevent IMO the library users to put an objects from the array aside, because the object wouldn't survive the array. And the programmers wouldn't be able to do anything about it - due encapsulation.
    Martin.
    I don't understand which problem you could be referring to.

  2. #32
    Join Date
    Feb 2010
    Posts
    16
    > There is a vast literature on GC. Modern collectors can work quite well
    > for a lot of uses, but they do tend to use a lot of memory. The
    > complexities are such that there isn't much I can say in a short message,
    > but "I cannot imagine" and "I do not think" should be validated against
    > the literature and/or backed with measurements.

    In the past I read a lot on garbage collection, e.g. here, or here, or here, or here etc.. That's why I don't understand how the simple ABI could be sufficient (for copying GC). But I don't say it's impossible.

    >I don't understand which problem you could be referring to.

    I'm refering to this, pp.24-26, and this. I would never (or very rarely) write

    void f(int i)
    {
    vector<unique_ptr<X>> v;
    v.push_back(make_X(i));
    v.push_back(make_X(j));
    // …
    }
    because then I would be bound by the fact that the vector v takes ownership of the X-es. If I modify the f and pass in an X-instance as an argument, I would lose ownership to the instance at the moment it is added to v. Thus I won't be able to pass into f instances that I need to use even after the control is returned from f.

    I would think about replacing shared_ptr with unique_ptr only when writing a performance-critical function (and then I would probably use raw pointers instead). By profession I'm a business programmer. And in this area of programming it is always good to follow the rule that "resources are much cheaper than programmers". Don't do optimizations where you don't need it.
    Last edited by Xarx; 03-10-2010 at 05:04 AM. Reason: clarification

  3. #33
    Join Date
    Feb 2010
    Posts
    19
    Quote Originally Posted by Xarx View Post
    > There is a vast literature on GC. Modern collectors can work quite well
    > for a lot of uses, but they do tend to use a lot of memory. The
    > complexities are such that there isn't much I can say in a short message,
    > but "I cannot imagine" and "I do not think" should be validated against
    > the literature and/or backed with measurements.

    In the past I read a lot on garbage collection, e.g. here, or here, or here, or here etc.. That's why I don't understand how the simple ABI could be sufficient (for copying GC). But I don't say it's impossible.
    Good. I don't claim to know how to do copying GC given the C++0x ABI and the related guarantees. However, I would be most reluctant to bet against a conjecture by Hans Boehm (look him up, he is a very distinguished GC researcher). He has a nasty habit of being right.

    Please note that many FAQs and much research related to GC are biased by data from specific workloads and languages. That's quite natural (unavoidable, especially in summary or popularized form), but it does often lead to overgeneralization (to all workloads and languages)

  4. #34
    Join Date
    Feb 2010
    Posts
    19
    Overviews and FAQs necessarily have very short examples, maybe you'll prefer this variant:

    vector<unique_ptr<X>> X_factory(some arguments)
    {
    vector<unique_ptr<X>> v;
    v.push_back(make_X(args0));
    v.push_back(make_X(args1));
    // …
    return v;
    }

  5. #35
    Join Date
    Feb 2010
    Posts
    19
    Quote Originally Posted by Xarx View Post
    >
    I would think about replacing shared_ptr with unique_ptr only when writing a performance-critical function (and then I would probably use raw pointers instead). By profession I'm a business programmer. And in this area of programming it is always good to follow the rule that "resources are much cheaper than programmers". Don't do optimizations where you don't need it.
    I'm sure that the "business programmer" vs 'systems programmer" affects our outlook, but I do not (emphatically not) consider unique_ptr vs shared-ptr a simple optimization (even though there are major performance differences). The distinction is logical. What I'm saying is that shared ownership is less fundamental that people think - in fact they try hard not to think about ownership at all and pay for that in program complexity, maintenance cost, as well as performance. For example, people who use shared_ptr simply to pass an object out of a function are doing "false sharing"; they don't actually share anything.

    GC in all its varieties allows people not to think about resource management in small simple programs (which is good) but doesn't always scale to programs where resource management is critical or where resource leaks are unacceptable (No, as you probably know, GC does not guarantee the absence of resource leaks). And no, I'm not against GC (as my work to get it into C++0x proves), but it is not a panacea and we must think harder about its role in various forms of programming.

  6. #36
    Join Date
    Feb 2010
    Posts
    16
    > vector<unique_ptr<X>> X_factory(some arguments)

    Take an ordinary function instead of a factory function.

    Code:
    unique_ptr<vector<X>> sort(unique_ptr<vector<X>>)
    This surely wouldn't work well. Perhaps the following would be better, if the sorting is meant to be in-place:

    Code:
    weak_ptr<vector<X>> sort(weak_ptr<vector<X>>)
    But if the function should return a sorted copy instead, the signature would have to be

    Code:
    unique_ptr<vector<X>> sort(weak_ptr<vector<X>>)
    And what signature would the sorting function have to be, if the implementation were to return the original vector in case it is already sorted (and a sorted copy otherwise)? Note that in this case I changed only the implementation, the specification of the sort function stays the same - nevertheless I have to modify the signature of the function.
    Last edited by Xarx; 03-10-2010 at 02:48 PM. Reason: clarification

  7. #37
    Join Date
    Feb 2010
    Posts
    19
    Quote Originally Posted by Xarx View Post
    > vector<unique_ptr<X>> X_factory(some arguments)

    Take an ordinary function instead of a factory function.

    Code:
    unique_ptr<vector<X>> sort(unique_ptr<vector<X>>)
    This surely wouldn't work well.
    Looks good to me: "give the vector to sort() and let sort() hand it back when its finished." What do you think might be a problem?

  8. #38
    Join Date
    Feb 2010
    Posts
    16
    > I'm sure that the "business programmer" vs 'systems programmer"
    > affects our outlook

    At minimal in that I'm more interested in the high-level language features than you are. :-)

    GC in all its varieties allows people not to think about resource management in small simple programs (which is good) but doesn't always scale to programs where resource management is critical or where resource leaks are unacceptable (No, as you probably know, GC does not guarantee the absence of resource leaks). And no, I'm not against GC (as my work to get it into C++0x proves), but it is not a panacea and we must think harder about its role in various forms of programming.
    I agree with you. But I began the discussion on GC because reference counting and proper garbage collection are for me just two alternative algorithms for automatic garbage management.

    There are two viewpoints - the one of object (class) providers, and the one of object users. And from the second viewpoint - the viewpoint of smart pointer users - they don't care which of the GC algorithms takes place. They only want it to handle the garbage correctly. And this is why I asked why shared_ptr is tied with the RC only instead of giving us a choice.

    Of course, from the first point of view the algorithms differ very much, but not from the second point of view.

  9. #39
    Join Date
    Feb 2010
    Posts
    16
    Quote Originally Posted by Bjarne Stroustr View Post
    Looks good to me: "give the vector to sort() and let sort() hand it back when its finished." What do you think might be a problem?
    Because I am the owner of the vector, and I don't want to get rid of the ownership just because I want the vector sorted.

  10. #40
    Join Date
    Nov 2003
    Posts
    4,118
    I wouldn't consider unique_ptr as an "optimized shared_ptr". As Bjarne said, they are completely different concepts. unique_ptr implements a safe model of move semantics. Move semantics can't always replace pure copying, as we all know, but when it can -- it avoids unnecessary and costly copying (it takes a while to digest perfect forwarding and move semantics). So the two classes are certainly not interchangeable. As for calling sort() etc al: the Standard Library recognizes movable vs copy constructible types and knows how to handle each safely.
    With respect to GC: I still haven't seen a GC that's suitable for destructors. Notice that all languages that have a built-in GC have sacrificed destructors (as well as a few other notions and conveniences) so the choice here is really tough. The ABI might change in the future but so long as C++0x doesn't have a proper GC, it's very hard to reach valid, unbiased conclusions about it.
    I know that there's tendency to look at other programming languages and implicitly assume that what they're doing is the right thing, and that C++ must clone those behaviors. I noticed that for example when people (committee members included) insisted that C++ must have finally.
    and BTW, I have to disagree with the "resources are cheaper than programmers". When you have to invest millions of dollars on "resources" (say a Cray machine), you'd probably be looking for an alternative in the form a trained programmer who can optimize the code. Look at the HipHop for PHP project for example. In spite of all the claims that hardware is cheap and PHP enables quick development, they eventually came to the conclusion that compiled C++ code is still cheaper.
    Danny Kalev

  11. #41
    Join Date
    Feb 2010
    Posts
    16
    > I wouldn't consider unique_ptr as an "optimized shared_ptr"

    I agree, and I didn't claimed the contrary. But it seems to me that Bjarne says that in most cases where I would naturally use shared_ptr or weak_ptr, a unique_ptr would be better:

    For almost all uses, I prefer unique ownership as represented by unique_ptr.
    I would say that unique_ptr in a function argument means that the function wants to take ownership of the argument. And unique_ptr returned from a function means that the function created that element. So I would say that in these rare situations unique_ptr can replace shared_ptr.

    Nonetheless, I believe this is just a misunderstanding.

    > I still haven't seen a GC that's suitable for destructors.

    I don't think a GC will ever be able to postpone calling destructors. Destructors by nature have to be called immediately. But this doesn't mean that everything that is placed in todays destructors must be called immediately. And this postponable code could be moved to finalizers - if C++ had such a thing.

    > I know that there's tendency to look at other programming languages
    > and implicitly assume that what they're doing is the right thing, and
    > that C++ must clone those behaviors. I noticed that for example when
    > people (committee members included) insisted that C++ must have finally.

    I think that there's always a chance to learn good things from designers of other languages. Because they don't have our prejudice (they have their own :-) ). Not everything that is in other languages is good, but there are a lot of good features that C++ lacks. And in this case I prefer copying their ideas to attempts to think it up "differently and better". And of course, similarity between languages helps newcommers and programmers that have to migrate between the "commercially valuable" languages. :-)

    > I have to disagree with the "resources are cheaper than programmers".

    I probably live in another world than you do. I've read that Crays exist, but haven't had access to any. My daily reality are Windows or Linux servers, or clusters of these. :-) But don't take mi literally - I'm aware that this "golden rule" of business programming has its limits. :-)

    Martin.

  12. #42
    Join Date
    Feb 2010
    Posts
    19
    Quote Originally Posted by Xarx View Post
    Because I am the owner of the vector, and I don't want to get rid of the ownership just because I want the vector sorted.
    You have two choices: (1) pass the ownership to whoever needs access and get it back again (as in my sort() example and (2) pass an ordinary pointer to a user (e.g. sort) and rely on the user not trying to use that pointer after the object is deleted.

    Note that you can (implicitly) delete the object by letting its unique-ptr go out of scope or give the unique_ptr to someone else before or when you return.

  13. #43
    Join Date
    Dec 2007
    Posts
    401
    > we consider C++ to be a modern language, don't we?
    > So we should compare it to other modern languages like C#,
    > Java or scripting languages, not to C.
    > Until C++ contains features that make high level C++ programming similarly
    > productive and easy to learn as programming in the other languages,
    > C++ will be becoming a "special purpose" language.
    > Currently C++ lacks those features, and C++0x does not much
    > to improve it. I'm saying that even though I like C++ more than e.g. C#.

    My view of C++ (and programming languages in general) is somewhat different. IMHO, there is no one true programming language that will be the best tool for writing all programs. There are many programming languages, and they differ in expressive power, and also differ in ease of mastering their use. A programming language that makes easy tasks trivial also tends to make difficult tasks impossible.

    C++ has an important role to play in programming because I have not seen any other language that can replace C++ in writing several kinds of programs - those that involve a very large code base, those that need to interoperate with diverse hardware and software, those where performance is critical. It also does not mean that C++ would be the best choice for all kinds of programs - a python script may be all that you need. While anything that can be done by a python script can be done by a C++ program, writing the C++ program would certainly be harder (in some case much harder). I don't think that we will ever be able to make C++ as easy to learn and use as, say, python, unless we are willing to sacrifice quite a lot of the expressive power of the language - the power that gives it a unique place, so unique that there are no substitutes for it, among modern programming languages.

    > I don't think a GC will ever be able to postpone calling destructors.
    > Destructors by nature have to be called immediately.

    Completely agree with that - why resource management is so much easier in C++ is because it has such a strong notion of initialization and deinitialization. That is what makes it possible to use RAII with such telling effect.

    > But this doesn't mean that everything that is placed in todays destructors
    > must be called immediately. And this postponable code could be moved to
    > finalizers - if C++ had such a thing.

    Well, Boehm's GC for C++ does support the idea of finalisers in C++; see
    http://www.hpl.hp.com/personal/Hans_...alization.html

    Though the caveats and guidelines that he gives are very important - among others:
    However, finalization should not be used in the same way as C++ destructors. In well-written programs there will typically be very few uses of finalization.
    Actions that must be executed promptly do not belong in finalizers. They should be handled by explicit calls in the code (or C++ destructors if you prefer).
    Scarce system resources should be managed explicitly whenever convenient. Use finalizers only as a backup mechanism for the cases that would be hard to handle explicitly.
    Last edited by vijayan; 03-11-2010 at 08:06 PM.

  14. #44
    Join Date
    Feb 2010
    Posts
    16
    > There are many programming languages, and they differ in expressive
    > power, and also differ in ease of mastering their use. A programming
    > language that makes easy tasks trivial also tends to make difficult
    > tasks impossible.

    At a general level I agree, but not in case of C++. Take into account that before Java and C#, C++ and C were the only (widespread) languages used for application and server programming - the task for which Java (in Linux world) and C# (in Windows world) are used nowadays. IMO this makes C++ comparable in its purpose to these two languages. But currently C++ loses, because the other two languages evolve much more rapidly, and they are much easier to use and learn. (Not that these are the only reasons. At least equally important is IMO that these languages are forced by strong companies - Sun and MS.)

    Concerning Boehm's GC: Note that it is not a C++ GC. It is a C garbage collector with C++ interface. This necessarily results in that this GC is conservative and not precise, because C alows nothing more. If this collector used facilities that C++ offers, it might be turned into a precise collector, which could increase it's usability - and change its design (e.g. concerning the finalizers). (Not that I'm saying that this is a bad GC!)

    Martin.
    Last edited by Xarx; 03-12-2010 at 09:29 AM. Reason: amendment

  15. #45
    Join Date
    Feb 2010
    Posts
    16
    > You have two choices: (1) pass the ownership to whoever needs
    > access and get it back again (as in my sort() example)

    When we consider ownership substantial and not arbitrary and random, then this is surely not the intended behaviour. Of course, technically this would work, but conceptually it would be a nonsense.

    > and (2) pass an ordinary pointer to a user (e.g. sort) and rely on
    > the user not trying to use that pointer after the object is deleted.

    This intention is best expressed by weak_ptr.

    What I originally wanted to say was that when we want to separate function specification and implementation, then often the only suitable return type of all the three smart pointer types is shared_ptr. Like in sort where an optimized implementation can return both the original vector and a new vector, depending on situation. In this case, neither unique_ptr nor weak_ptr would work.

    Code:
    shared_ptr<vector<T>> sort(weak_ptr<vector<T>>)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center