Um, I'm not a regular drug user but how are the effects of Cannabis beneficial to gaming?
Surprising, but I've had a number of friends who claim they can just coast through games if they're stoned. Apparently it makes them feel in "the zone" non-stop, if that makes any sense. A lot of any competitive activity is FEELING like you're on top of things, and I think that's where it helps; it's a mindset kind of thing. For me though, I'd probably just end up wandering off into a virtual corner and staring at something shiny.
Doesn't matter how far behind you are in their market if the only thing in question is your own. NVIDIA has consistently put out vastly superior graphics hardware than Intel.
That's... not such a good idea if you live in the city. Plus, I'm not sure they'd actually follow instructions like that (liability and all) unless you call and register the request with their dispatch or whatever they call it.
Owning the game myself--despite the reviews; it just interested me--and having sunk some hours into it, I can say that, despite its flaws, it is really quite enjoyable. I can see some immediate problems reviewers might have, since it takes a while to get used to the way the unconventional controls and camera work. Now that I'm comfortable with it, though, it's really just a fun dungeon crawl. It has its challenges, and its fun little secret zones, and it really does the "loot whore" thing very well.
Honestly, I'm pretty comfortable saying that all of these horrendously bad reviews are just people who simply decided they weren't going to like it, and weren't going to try to learn to play it. I, for one, am hoping people look past the imbeciles who decided they'd give it a 55% review just because they didn't like the way it looked at them, because I, for one, would enjoy a second installment.
P.S. Protip: Switch the camera to "Strategic" mode IMMEDIATELY. The default camera mode is horrendous.
Gonna have to disagree with you on auto-scaling. And don't get me wrong, I absolutely HATED it in Oblivion, but that's because it ruined the sense of discovery and achievement in an open-ended game. In other words, the reason I think auto-scaling ruined Oblivion is that it ended up feeling like I had hundreds of places to go, all very nearly identical. On the other hand, Too Human is VERY linear, and I have no problem at all with the auto-scaling. It seems well balanced enough that enemies simply stay challenging regardless of where I venture to go (although it doesn't get challenging until the second/third zone where it starts throwing a horde of goblins, 20 dark elves and a few trolls at you all at once), which I think is entirely appropriate within the context of this game.
Theoretically, you are correct. But there is no time to read everything, especially when under pressure to finish a project on time.
Yeah, I'm just crazy that I read the boost docs for fun;)
I am talking specifically about C++, which has most values allocated in the stack. That's the reason C++ produces the fastest code anyway.
The use of the stack in C++ is fairly limited. It's really only for small objects that can be passed around by value, and not for long-lived objects. Like I was saying, anything complex enough to have a non-trivial destructor is probably going to be too complex to be useful allocated on the stack.
The one great thing in C++, and the reason I don't give up on it, it's that destructors are called at procedure exit. That's so great! it helps with a lot of problems.
Well, that's the whole point of smart pointers. You get the EXACT same kind of determinism with your destruction, without having to use only local variables.
Your definition of RAII is wider than mine.
That's Bjarne Stroustrup's definition. He coined it as a general design pattern that should be used whenever possible.
Smart pointers are not for collections only. I am surprised that almost everyone has such a narrow scope, as if no one has ever made a complex program.
For example, in my current project...
Memory pools? Now clearly you know the project better than I do, but for situations like you describe, I don't think standard smart pointers OR garbage collection are really appropriate. Large scale allocation/deallocation of homogenous data types, that really sounds like something where you want all those resources in a pre-allocated memory pool that you can just draw from and release to at a whim with virtually no overhead compared to memory allocation in either system. Then again, maybe there are factors preventing the system being designed around memory pools? Anyway, that's certainly the solution I would choose given those criteria.
Well, I hope that after reading this last post of mine, you understand what kind of situation I am into. C++ is considered a systems language, and so our customers demand it. But their problems are big and complex, and if C++ had GC, the solutions would be better from all perspectives (faster coding, less debugging, less expensive, etc).
Is there a reason you can't use the very excellent Boehm garbage collector library for C++? Obviously if there's a reason your particular project will benefit from it, it might be worth considering. My argument is really only against how appropriate that functionality would be as a core feature of C++.
It's not possible to search for something when you don't know it exists.
You're right; I think I didn't phrase that properly. I was trying to say that the Boost documentation is such that you are best served by thoroughly reading the entire documentation on a library before using it. There are too many hidden/non-obvious things in there that end up being very important to just pick it up and use it and only refer to the documentation as needed, sadly.
But you don't have to release them manually! I've said it twice before: you use RAII for files, sockets etc, and GC for anything else. It's simple, it works, and it covers most cases.
Yes, which is great when everything of this sort can reside on the equivalent of the C++ stack (assuming the GC system/language you're using has such a distinction and EVERYTHING isn't like a heap allocation). Am I missing something here? All RAII means is that the resource is allocated when the object encapsulating it is created, and deallocated when that object is destroyed. You can have RAII in a GC environment too, but the problem is it's non-deterministic (you don't generally know when it will actually happen).
I guess my question is, how do you go about achieving determinstic object destruction in a GC environment, which is what's required for RAII to be effective with non-trivial destructors? As far as I'm aware, you don't, and that's one of the drawbacks.
It's an overhead that, if you don't use many smart pointers, it's negligible, but when you use thousands of them in arrays or collections, it starts to show, especially when measured against GC.
It's an overhead that adds up if you are passing around thousands of smart pointers, not just leaving them in collections. Keep in mind that C++ collections usually to pass/return their elements by reference, so there are no copy semantics in accessing a smart pointer in a collection and thus no additional overhead outside of whatever is required for dereferencing. I honestly can't think of a reason you would ever be passing thousands of smart pointers around on a regular basis. I'm sure there may well be, but not in designs I've ever had to deal with.
Additionally, many of your arguments assume that the pointer is being used in a multi-threaded environment, AND that there is no guarantee of any kind of thread locality. Otherwise atomic operations would simply be unnecessary.
I will say, this debate has been productive for me. While I'm not convinced that any use cases I'm concerned with would benefit from GC, you do make the case for there BEING use cases where it is potentially advantageous. It does make sense that if you find yourself in the situation of passing a large number of pointers among threads on a regular basis, GC would be more efficient. Passing within a single thread, though, I'd like to see some sort of benchmark between the two. My intuition tells me that GC would only pull ahead in that case after what I would describe as an "unreasonable" number of pointer copies. Could be wrong though.
Indeed, I was not aware of it. But the docs don't have it.
Yeah, it's definitely buried in the documentation, but it is there. The link I gave you was direct to the boost docs. Unfortunately a lot of the stuff is like that, and I'd really recommend going through the documentation for any boost lib thoroughly before using it. It helps a LOT.
I guess we simply have conflicting views on the ultimate goal of various resource management schemes. My take is that whatever memory management scheme you use, the real point, and the primary consideration, is essentially twofold: how easy it makes the task of managing memory, and how many potential errors it can eliminate.
My point regarding garbage collection is that one of its primary design goal (if not the primary design goal) is to eliminate to need to manually track allocations and deallocations (essentially everything should be "fire and forget" in an ideal GC environment). This eliminates the burden of having to do it manually, and the potential errors of forgetting to do so. I say this with respect to the assumption that raw pointer handling (new/delete or malloc/free) is essentially our "memory management baseline." For complex resources, however, my complaint against GC is that it introduces the overhead of having a collection process running in the background (or at various intervals or whatever), but without any usability benefits over just using new/delete. I still have the burden of having to release them manually, and the potential errors of forgetting to do so. If I have to remember to release my resources when I'm done with them anyway, why would I use GC in the first place and not just stick with new/delete? In practice it's effectively the same--I'll be manually allocating and manually releasing resources either way.
This is why I personally prefer to use smart pointers most of the time, particularly in that most of the programming I do these days makes extensive use of limited resources that must be released promptly when they are no longer absolutely needed. I prefer just being able to simply drop the pointer and let it fall out of scope, no further intervention needed, and its various resources are all immediately freed. This allows me to share pointers among various components without having to worry about tracking when they are all done with it--when they are, it's all taken care of behind the scenes as it were. This is as opposed to a garbage collection scheme, where I would still have to track and manually release those resources if I want them to be returned to the system without having to wait on the collection cycle, which can be very important.
Cyclic pointers are a problem, but one that can be designed around, particularly once you get used to doing so. Probably this is the real significant drawback of smart pointers vs. garbage collection, and the one consideration that might make me prefer GC under certain circumstances where there are a large number of them.
As for efficiency, that goes both ways. Garbage collection introduces its own overhead. Generally the overhead just manifests differently between smart pointers and GC though. With smart pointers the added overhead tends to be more spread out, as pointers are individually allocated and drop out of scope. With GC, it tends to come in big "lumps," when the collector decides to scan for dependencies. As for atomic increments/decrements, those tend to be fairly fast, as (correct me if I'm wrong) most modern processors provide machine level commands for those sorts of atomic operations without having to resort to locks/mutexes. Not as fast as a non-atomic operation of the same sort, but fast enough not to be a problem in this context.
A quick search of dice.com reveals 23,169 jobs for PHP, Ruby, Python, Java, and C# combined (using a search returning any of those keywords). It reveals 7,926 for C++ alone. I'm not so worried for C++;)
It's that arrays are still not first class objects in the language.
Well, this is arguable. Arrays are essentially pointers in C++. Semantically you can define sized arrays at compile time, but a dynamically sized array (what you seem to be referring to) is just a pointer with a size counter. That sort of thing is NOT the sort of thing C++ fundamentally treats as deserving to be a "POD" type, and is perfectly find residing in the STL (std::vector). I, personally, see absolutely no problem with this.
I don't see any keywords for specifying the endianness of an integer - how useful would that be.. to be able to say "bigend int foo" or "littleend int foo".
Not very? I dunno, for cross-platform work maybe? I've honestly never had a particular urge to switch the endianness of an integer, or come across a situation where it would be terribly important. Do you have an example? I honestly can't think of much.
I'd like to be able to specify a structure or a class which could have a single value be composed of a few bits in utterly random places in it. In other words, you could say something like:
struct foo {
int a bits 1-2 this+1.2, bits 4-5 this+3.3
};
which you would read as int a bits 1-2 are at a byte and bit offset from the structure.
This looks like something you could accomplish with bit fields. But maybe I'm not reading your meaning correctly? Is there something here that couldn't be accomplished with a well laid out bit field?
And, while we were at it, how about packed pointers. AMD64 has 64 bit pointers and we can easily stuff some extra crap at the high end of them if the compiler knew to strip it out before we dereferenced them. You could implement that as a mov and an and.
This is really a feature I would classify as "arguably" useful. As in, maybe something that would come into play for embedded development, or driver development? Honestly, again, not something I've ever really wanted, but maybe you could provide another example why? Definitely not something I'd consider important for inclusion into the core language, that's for sure.
To me, a language like C or C++ is that you can evolve your own exact brick of memory and carve it up in some way... really, the idea of C is almost to be just to be a very fancy macro assembler and C++ was to throw a bit of object orientedness around it, if you want.
But, instead, we have iterators and containers and ever more powerful templates and, gross, garbage collection support...
C and C++ are for getting things done. Having a fancy, user-readable assembly language may be great for people who are doing embedded and driver development, but for the vast majority of us, we WANT high level features which make the language as expressive as possible. There's nothing stopping you from just confining yourself to the lowest level corners of the languages, popping inline assembly in where you want it, but that's not really the POINT of the language.
The great irony, of course, is that C++ templates and, wow, look at generics in C++0x, are so incredibly powerful that, what we have is a extremely high level language that still doesn't do comma delimited output of numbers.
What? Again, this doesn't make sense to me. I can name have a dozen methods of varying complexity to accomplish comma delimited output. This another one of those things that doesn't belong in the CORE language. This is something that SOME people need to do, and SOME don't, depending on the vagaries of their projects. As such, it absolutely belongs in an external library, and again not as a core language feature.
To be honest, what seems the most schizophrenic here is your claiming in one paragraph that you want C++ to be some sort of glorified assembly language, and then going on to complain that it doesn't do comma delimited output. I'm sorry, I just don't get it.
I can only speak from personal experience, which gives me good cause to disagree strongly with your claim. Perhaps much of what you use are web apps, I can't speak to that. In my usage, however, an absolutely overwhelming majority of the software I use is, as you put it, the sort of thing you'd find in a setup.exe. That goes for both home usage and what I use at the large company I work for (we have a web portal, but everything substantive still goes on in native applications).
I'll admit that the "buzz" certainly has moved away from traditional application development, but fads are what fads are. I've never really thought this whole Web 2.0, everything in a "cloud" business C++ is long past its popular fad phase.
That's all anecdotal though, so maybe the "average" mileage is different.
That is, until you try to combine it with other libraries, like Qt, for example. Boost has a namespace signals, Qt has a #define signals. Yes, you can solve the problem using the preprocessor, but boost was supposed to be 'plug-n-play'...
That's really the case with any situation where you have two libraries which implement the same functionality though. It's hardly a problem that's confined to Boost, or even C++. The nice thing about boost signals though is you can pass ANY functor (functions, member functions, function objects) through them.
Smart pointers are difficult to manage in the context of complex object relationships. See my other post for more info.
Regarding your other post, while I'm not 100% sure what you're getting at, if it is what I think it is, then you are actually incorrect. See here. I can certainly understand being averse to Boost's smart pointer implementation if you weren't aware of this functionality.
The idea that destructors don't play well with GC is largely a myth. Non-trivial jobs should not be done in destructors. But even if they are done in destructors, they should be invoked using RAII style. The destructor is only a function, so it can be called normally just like any other C++ function.
But then you're more or less defeating the entire point of garbage collection, which is not having to worry about manually releasing any resources when they go out of scope. Once you start requiring that resources be manually deallocated before being let out of scope, you've just lost any real benefit of using a GC model in the first place. Sure GC *can* work with non-trivial destructors, but in doing so you lose the real benefits you've gotten from GC in the first place, which is why I claim that smart pointers are actually much more suited to such a situation because they retain that same benefit.
As I explain in my other post, the problems of cyclic references introduced indirectly, the situation where you only have 'this' and you should use shared_ptrs, etc are great problems and you should not underestimate them.
I do concede that cyclic references are the weakest aspect of smart pointers, and do require a little more work in the design of your software to avoid them. I will admit though, if you have a situation where cyclic references are legion, then GC might be a superior choice. With limited cyclic references, however, weak smart pointers are a perfectly elegant solution. It's usually obvious from a design perspective which pointers should be made weak.
As far as I'm concerned, the ones who agree to commit some sort of fraud as part of their "victim" role in the scam certainly do. Keep in mind that many of these scams require some very questionable activity (e.g. agreeing to participate in a money laundering operation to get a cut of it) on the part of their "victims." Not only were they stupid enough to fall for the scam, but they were greedy and unethical enough to ostensibly commit a crime in the process. No sympathy here for ANY the participants of those sorts of scams.
I looked at that, and at first it seemed, well, this is fair. A lot of these things are drawbacks, and it's pretty well laid out. Then I read into it a little further... and I really have to wonder. A lot of it is just WILDLY exaggerated. I mean, the author clearly tried to blow some minor problems up to ridiculous proportions. Some of the stuff in there is just absurd. Gems like this:
[8.2] What happens if you assign to a reference?
FAQ: A reference is the object, so of course you assign to the referent object.
FQA: Which means that you can't understand the effect of a statement as simple as a=b; without knowing whether a is a reference or not. A nice feature complementary to references (which make you wonder what "a" means) is operator overloading (which makes you wonder what "=" means). Be careful as you work your way through a quagmire of C++ code.
I'm sorry, but that's just inane. Of course you can't know what the effect of an assignment will be without knowing the actual type of what you're assigning to. How is this news? How is this important? Unfortunately a great deal of that site you linked to is filled with useless fluff like this.
Yeah, that article says a lot. Unfortunately, upon close inspection, very little of it is of much value.
Um, I'm sorry, but... what the hell are you talking about? Restricting pointers? What? Did we read, like, different articles or something? I don't know if I'd call smart pointers the kind of "automatic memory management" I'd ever complain about. All they really are is essentially a regular * that has the decency to delete itself the moment all its references go out of scope. And completely 100% optional at that. As will be garbage collection if it ever becomes part of the core standard (it certainly won't in this next revision). And what's wrong with a bigger library? You don't have to USE the extra features, and they're mostly all templates anyway, so it's hardly increasing the size of your binary when you don't. I don't know about you, but I prefer to have the features available for me when and if I want them...
How is this +4 Insightful? Am I missing something?
To give you a straightforward answer, first off, Objective-C and C++ really are two very different languages. The new specification is of C++, and has no effect or relation with respect to Objective-C.
With that out of the way, I for one feel that the new spec is a VERY clear improvement over the current C++ spec on a number of fronts. Not to be rude, but if you RTFA it really does go over them point by point. I for one am going to enjoy the "auto" keyword greatly. Rvalue references will eliminate a lot of annoyance in having to do the same repetitive optimization workarounds. And just in general the syntax is going to get a lot cleaner. So the answer, in short, is yes, it is a clear improvement, and one that I'm looking forward to.
Nothing else in your post either supports, or even directly addresses this assertion.
It's not that C++ isn't good, its just that its harder to do things in it then it is to do those same things in either C# or Java. Harder to do means more expensive, and businesses all over are having to tighten their purse strings.
This is the same bullshit that's trotted out there every time this topic comes up, and it's no more true now than it ever was, which is not at all. If you do a little looking around, you'll find very elegant libraries that support every single feature you'll see in ANY other imperative language, and MANY declarative language features to boot. If you're against code reuse and third party libraries on some sort of general principle, then you're kinda missing the whole point of C++.
I'll be blunt, maybe an ass, maybe a troll, but having used all three of those languages extensively, I can say with almost absolute certainty that the only reason you should be having so much more trouble doing things in C++ (ESPECIALLY as compared to those two languages) is that you're either a very poor C++ programmer or have a pathological aversion to third party libraries.
In fact C++ is barely managing to hold its own any more against C# and Java.
Another thing that's been very much in the vogue to say lately, but I just haven't seen any meaningful evidence for. I think Bjarne covered this topic fairly even-handedly in TFA, and if he's to be believed then C++ usage is not suffering like popular belief seems to indicate. The crux of it being that web scripting was never a strong domain of C++ in the first place, and in actual applications programming C++ is still the leader of the pack.
I'm going to have to disagree with you. For CERTAIN kinds of optimization, I'll definitely agree with you. Things like algorithmic optimization can and should absolutely wait until the whole program is finished. Certain kinds of optimization, though, need to be accounted for from the start as part of the higher level design. Or example, the choice to use a formal graph representation of your data, or a specific database representation, or (to pick an example from 3D graphics) the kind of visibility determination algorithm you use, that has implications on the design of your entire program and IS something you should optimize for in the design from the very beginning, because changing that kind of thing at the end requires MAJOR refactoring. Just my two cents, but I think it's dangerous to say you should NEVER consider optimization until the end.
First off, if you have a problem with using external libraries, then you just won't get anywhere with a C/C++. They are VERY general purpose, and intentionally so, and the whole idea is that implementation specific things are supposed to be provided in libraries, rather than the core language. That said:
1. Boost is actually very easy to integrate for most of its features. A few (small handful) of its components require compilation, but the vast majority of them are template-based and header only. Meaning just include a header file and there you go, you're using boost. No extra compilation/installation required.
2. This kind of thing is GREAT for doing small scripts, but HORRIBLE for doing large complex applications where type safety can be VERY important for avoiding bugs. If all you ever do are small, quick, limited scripts, then you're absolutely right that you should avoid C++, that's certainly not what it was meant for, and not so much the domain of a strongly typed language. For things like the software that runs large financial institutions and whatnot, there's a reason code like that should be avoided at all costs.
3. I have trouble imagining a situation where a real garbage collector would ever be superior to an RAII model with shared smart pointers for stuff allocated on the heap, outside of plugging up a leaking legacy app. Maybe for very simple programs, but once you get non-trivial destructors (for example, with objects that lock system resources), then you start having to do manual memory management in your GC environment anyway, and end up with a horribly ugly conglomeration of "mixed metaphors" as it were. Smart pointers really give you the best of both worlds: deterministic destruction, without having to worry about manually releasing anything. It's just a matter of getting used to declaring a smart pointer wherever you would have a "type *name" instead. So yes, I'd argue they ARE a substitute for garbage collection in almost any situation.
4. Sorry to be blunt, but you should probably RTFA on this one. The problem is solved through "concepts," which is the part of the new specification which deals with this specifically. It's essentially a C++ implementation of the "design by contract" metaphor.
5. In this case "can be" equates to "do whatever you like and it'll be portable on all major general purpose computers, and who uses Ruby or Python on embedded platforms anyway?" If you are able to compile with GCC, which is the case for pretty much every computer/OS combination in existence, then you can count on it being pretty damn portable. If you are programming for something like an ATM or a set-top box, then you probably aren't going to be using a high level scripting language anyway.
6. Yeah, it can get ugly. Thankfully this will be largely fixed with the "auto" keyword in C++0x.
Surprising, but I've had a number of friends who claim they can just coast through games if they're stoned. Apparently it makes them feel in "the zone" non-stop, if that makes any sense. A lot of any competitive activity is FEELING like you're on top of things, and I think that's where it helps; it's a mindset kind of thing. For me though, I'd probably just end up wandering off into a virtual corner and staring at something shiny.
Doesn't matter how far behind you are in their market if the only thing in question is your own. NVIDIA has consistently put out vastly superior graphics hardware than Intel.
That's... not such a good idea if you live in the city. Plus, I'm not sure they'd actually follow instructions like that (liability and all) unless you call and register the request with their dispatch or whatever they call it.
Owning the game myself--despite the reviews; it just interested me--and having sunk some hours into it, I can say that, despite its flaws, it is really quite enjoyable. I can see some immediate problems reviewers might have, since it takes a while to get used to the way the unconventional controls and camera work. Now that I'm comfortable with it, though, it's really just a fun dungeon crawl. It has its challenges, and its fun little secret zones, and it really does the "loot whore" thing very well.
Honestly, I'm pretty comfortable saying that all of these horrendously bad reviews are just people who simply decided they weren't going to like it, and weren't going to try to learn to play it. I, for one, am hoping people look past the imbeciles who decided they'd give it a 55% review just because they didn't like the way it looked at them, because I, for one, would enjoy a second installment.
P.S. Protip: Switch the camera to "Strategic" mode IMMEDIATELY. The default camera mode is horrendous.
Gonna have to disagree with you on auto-scaling. And don't get me wrong, I absolutely HATED it in Oblivion, but that's because it ruined the sense of discovery and achievement in an open-ended game. In other words, the reason I think auto-scaling ruined Oblivion is that it ended up feeling like I had hundreds of places to go, all very nearly identical. On the other hand, Too Human is VERY linear, and I have no problem at all with the auto-scaling. It seems well balanced enough that enemies simply stay challenging regardless of where I venture to go (although it doesn't get challenging until the second/third zone where it starts throwing a horde of goblins, 20 dark elves and a few trolls at you all at once), which I think is entirely appropriate within the context of this game.
I guess at this point is just comes down to us having very different experiences with the use of C++.
Yeah, I'm just crazy that I read the boost docs for fun ;)
The use of the stack in C++ is fairly limited. It's really only for small objects that can be passed around by value, and not for long-lived objects. Like I was saying, anything complex enough to have a non-trivial destructor is probably going to be too complex to be useful allocated on the stack.
Well, that's the whole point of smart pointers. You get the EXACT same kind of determinism with your destruction, without having to use only local variables.
That's Bjarne Stroustrup's definition. He coined it as a general design pattern that should be used whenever possible.
Memory pools? Now clearly you know the project better than I do, but for situations like you describe, I don't think standard smart pointers OR garbage collection are really appropriate. Large scale allocation/deallocation of homogenous data types, that really sounds like something where you want all those resources in a pre-allocated memory pool that you can just draw from and release to at a whim with virtually no overhead compared to memory allocation in either system. Then again, maybe there are factors preventing the system being designed around memory pools? Anyway, that's certainly the solution I would choose given those criteria.
Is there a reason you can't use the very excellent Boehm garbage collector library for C++? Obviously if there's a reason your particular project will benefit from it, it might be worth considering. My argument is really only against how appropriate that functionality would be as a core feature of C++.
You're right; I think I didn't phrase that properly. I was trying to say that the Boost documentation is such that you are best served by thoroughly reading the entire documentation on a library before using it. There are too many hidden/non-obvious things in there that end up being very important to just pick it up and use it and only refer to the documentation as needed, sadly.
Yes, which is great when everything of this sort can reside on the equivalent of the C++ stack (assuming the GC system/language you're using has such a distinction and EVERYTHING isn't like a heap allocation). Am I missing something here? All RAII means is that the resource is allocated when the object encapsulating it is created, and deallocated when that object is destroyed. You can have RAII in a GC environment too, but the problem is it's non-deterministic (you don't generally know when it will actually happen).
I guess my question is, how do you go about achieving determinstic object destruction in a GC environment, which is what's required for RAII to be effective with non-trivial destructors? As far as I'm aware, you don't, and that's one of the drawbacks.
It's an overhead that adds up if you are passing around thousands of smart pointers, not just leaving them in collections. Keep in mind that C++ collections usually to pass/return their elements by reference, so there are no copy semantics in accessing a smart pointer in a collection and thus no additional overhead outside of whatever is required for dereferencing. I honestly can't think of a reason you would ever be passing thousands of smart pointers around on a regular basis. I'm sure there may well be, but not in designs I've ever had to deal with.
Additionally, many of your arguments assume that the pointer is being used in a multi-threaded environment, AND that there is no guarantee of any kind of thread locality. Otherwise atomic operations would simply be unnecessary.
I will say, this debate has been productive for me. While I'm not convinced that any use cases I'm concerned with would benefit from GC, you do make the case for there BEING use cases where it is potentially advantageous. It does make sense that if you find yourself in the situation of passing a large number of pointers among threads on a regular basis, GC would be more efficient. Passing within a single thread, though, I'd like to see some sort of benchmark between the two. My intuition tells me that GC would only pull ahead in that case after what I would describe as an "unreasonable" number of pointer copies. Could be wrong though.
Yeah, it's definitely buried in the documentation, but it is there. The link I gave you was direct to the boost docs. Unfortunately a lot of the stuff is like that, and I'd really recommend going through the documentation for any boost lib thoroughly before using it. It helps a LOT.
I guess we simply have conflicting views on the ultimate goal of various resource management schemes. My take is that whatever memory management scheme you use, the real point, and the primary consideration, is essentially twofold: how easy it makes the task of managing memory, and how many potential errors it can eliminate.
My point regarding garbage collection is that one of its primary design goal (if not the primary design goal) is to eliminate to need to manually track allocations and deallocations (essentially everything should be "fire and forget" in an ideal GC environment). This eliminates the burden of having to do it manually, and the potential errors of forgetting to do so. I say this with respect to the assumption that raw pointer handling (new/delete or malloc/free) is essentially our "memory management baseline." For complex resources, however, my complaint against GC is that it introduces the overhead of having a collection process running in the background (or at various intervals or whatever), but without any usability benefits over just using new/delete. I still have the burden of having to release them manually, and the potential errors of forgetting to do so. If I have to remember to release my resources when I'm done with them anyway, why would I use GC in the first place and not just stick with new/delete? In practice it's effectively the same--I'll be manually allocating and manually releasing resources either way.
This is why I personally prefer to use smart pointers most of the time, particularly in that most of the programming I do these days makes extensive use of limited resources that must be released promptly when they are no longer absolutely needed. I prefer just being able to simply drop the pointer and let it fall out of scope, no further intervention needed, and its various resources are all immediately freed. This allows me to share pointers among various components without having to worry about tracking when they are all done with it--when they are, it's all taken care of behind the scenes as it were. This is as opposed to a garbage collection scheme, where I would still have to track and manually release those resources if I want them to be returned to the system without having to wait on the collection cycle, which can be very important.
Cyclic pointers are a problem, but one that can be designed around, particularly once you get used to doing so. Probably this is the real significant drawback of smart pointers vs. garbage collection, and the one consideration that might make me prefer GC under certain circumstances where there are a large number of them.
As for efficiency, that goes both ways. Garbage collection introduces its own overhead. Generally the overhead just manifests differently between smart pointers and GC though. With smart pointers the added overhead tends to be more spread out, as pointers are individually allocated and drop out of scope. With GC, it tends to come in big "lumps," when the collector decides to scan for dependencies. As for atomic increments/decrements, those tend to be fairly fast, as (correct me if I'm wrong) most modern processors provide machine level commands for those sorts of atomic operations without having to resort to locks/mutexes. Not as fast as a non-atomic operation of the same sort, but fast enough not to be a problem in this context.
A quick search of dice.com reveals 23,169 jobs for PHP, Ruby, Python, Java, and C# combined (using a search returning any of those keywords). It reveals 7,926 for C++ alone. I'm not so worried for C++ ;)
Well, this is arguable. Arrays are essentially pointers in C++. Semantically you can define sized arrays at compile time, but a dynamically sized array (what you seem to be referring to) is just a pointer with a size counter. That sort of thing is NOT the sort of thing C++ fundamentally treats as deserving to be a "POD" type, and is perfectly find residing in the STL (std::vector). I, personally, see absolutely no problem with this.
Not very? I dunno, for cross-platform work maybe? I've honestly never had a particular urge to switch the endianness of an integer, or come across a situation where it would be terribly important. Do you have an example? I honestly can't think of much.
This looks like something you could accomplish with bit fields. But maybe I'm not reading your meaning correctly? Is there something here that couldn't be accomplished with a well laid out bit field?
This is really a feature I would classify as "arguably" useful. As in, maybe something that would come into play for embedded development, or driver development? Honestly, again, not something I've ever really wanted, but maybe you could provide another example why? Definitely not something I'd consider important for inclusion into the core language, that's for sure.
C and C++ are for getting things done. Having a fancy, user-readable assembly language may be great for people who are doing embedded and driver development, but for the vast majority of us, we WANT high level features which make the language as expressive as possible. There's nothing stopping you from just confining yourself to the lowest level corners of the languages, popping inline assembly in where you want it, but that's not really the POINT of the language.
What? Again, this doesn't make sense to me. I can name have a dozen methods of varying complexity to accomplish comma delimited output. This another one of those things that doesn't belong in the CORE language. This is something that SOME people need to do, and SOME don't, depending on the vagaries of their projects. As such, it absolutely belongs in an external library, and again not as a core language feature.
To be honest, what seems the most schizophrenic here is your claiming in one paragraph that you want C++ to be some sort of glorified assembly language, and then going on to complain that it doesn't do comma delimited output. I'm sorry, I just don't get it.
I can only speak from personal experience, which gives me good cause to disagree strongly with your claim. Perhaps much of what you use are web apps, I can't speak to that. In my usage, however, an absolutely overwhelming majority of the software I use is, as you put it, the sort of thing you'd find in a setup.exe. That goes for both home usage and what I use at the large company I work for (we have a web portal, but everything substantive still goes on in native applications).
I'll admit that the "buzz" certainly has moved away from traditional application development, but fads are what fads are. I've never really thought this whole Web 2.0, everything in a "cloud" business C++ is long past its popular fad phase.
That's all anecdotal though, so maybe the "average" mileage is different.
That's really the case with any situation where you have two libraries which implement the same functionality though. It's hardly a problem that's confined to Boost, or even C++. The nice thing about boost signals though is you can pass ANY functor (functions, member functions, function objects) through them.
Regarding your other post, while I'm not 100% sure what you're getting at, if it is what I think it is, then you are actually incorrect. See here. I can certainly understand being averse to Boost's smart pointer implementation if you weren't aware of this functionality.
But then you're more or less defeating the entire point of garbage collection, which is not having to worry about manually releasing any resources when they go out of scope. Once you start requiring that resources be manually deallocated before being let out of scope, you've just lost any real benefit of using a GC model in the first place. Sure GC *can* work with non-trivial destructors, but in doing so you lose the real benefits you've gotten from GC in the first place, which is why I claim that smart pointers are actually much more suited to such a situation because they retain that same benefit.
I do concede that cyclic references are the weakest aspect of smart pointers, and do require a little more work in the design of your software to avoid them. I will admit though, if you have a situation where cyclic references are legion, then GC might be a superior choice. With limited cyclic references, however, weak smart pointers are a perfectly elegant solution. It's usually obvious from a design perspective which pointers should be made weak.
As far as I'm concerned, the ones who agree to commit some sort of fraud as part of their "victim" role in the scam certainly do. Keep in mind that many of these scams require some very questionable activity (e.g. agreeing to participate in a money laundering operation to get a cut of it) on the part of their "victims." Not only were they stupid enough to fall for the scam, but they were greedy and unethical enough to ostensibly commit a crime in the process. No sympathy here for ANY the participants of those sorts of scams.
I can't tell if you're writing in the voice of an Australian, Irishman, or merely a very confused cowboy.
I submit, as evidence of scams dating back a good long ways, the simple existence of the following phrase: caveat emptor.
There's a reason Robin Hood is such a beloved romantic figure. Steal from the rich and give to the poor indeed.
I looked at that, and at first it seemed, well, this is fair. A lot of these things are drawbacks, and it's pretty well laid out. Then I read into it a little further... and I really have to wonder. A lot of it is just WILDLY exaggerated. I mean, the author clearly tried to blow some minor problems up to ridiculous proportions. Some of the stuff in there is just absurd. Gems like this:
I'm sorry, but that's just inane. Of course you can't know what the effect of an assignment will be without knowing the actual type of what you're assigning to. How is this news? How is this important? Unfortunately a great deal of that site you linked to is filled with useless fluff like this.
Yeah, that article says a lot. Unfortunately, upon close inspection, very little of it is of much value.
Um, I'm sorry, but... what the hell are you talking about? Restricting pointers? What? Did we read, like, different articles or something? I don't know if I'd call smart pointers the kind of "automatic memory management" I'd ever complain about. All they really are is essentially a regular * that has the decency to delete itself the moment all its references go out of scope. And completely 100% optional at that. As will be garbage collection if it ever becomes part of the core standard (it certainly won't in this next revision). And what's wrong with a bigger library? You don't have to USE the extra features, and they're mostly all templates anyway, so it's hardly increasing the size of your binary when you don't. I don't know about you, but I prefer to have the features available for me when and if I want them...
How is this +4 Insightful? Am I missing something?
To give you a straightforward answer, first off, Objective-C and C++ really are two very different languages. The new specification is of C++, and has no effect or relation with respect to Objective-C.
With that out of the way, I for one feel that the new spec is a VERY clear improvement over the current C++ spec on a number of fronts. Not to be rude, but if you RTFA it really does go over them point by point. I for one am going to enjoy the "auto" keyword greatly. Rvalue references will eliminate a lot of annoyance in having to do the same repetitive optimization workarounds. And just in general the syntax is going to get a lot cleaner. So the answer, in short, is yes, it is a clear improvement, and one that I'm looking forward to.
Nothing else in your post either supports, or even directly addresses this assertion.
This is the same bullshit that's trotted out there every time this topic comes up, and it's no more true now than it ever was, which is not at all. If you do a little looking around, you'll find very elegant libraries that support every single feature you'll see in ANY other imperative language, and MANY declarative language features to boot. If you're against code reuse and third party libraries on some sort of general principle, then you're kinda missing the whole point of C++.
I'll be blunt, maybe an ass, maybe a troll, but having used all three of those languages extensively, I can say with almost absolute certainty that the only reason you should be having so much more trouble doing things in C++ (ESPECIALLY as compared to those two languages) is that you're either a very poor C++ programmer or have a pathological aversion to third party libraries.
Another thing that's been very much in the vogue to say lately, but I just haven't seen any meaningful evidence for. I think Bjarne covered this topic fairly even-handedly in TFA, and if he's to be believed then C++ usage is not suffering like popular belief seems to indicate. The crux of it being that web scripting was never a strong domain of C++ in the first place, and in actual applications programming C++ is still the leader of the pack.
I'm going to have to disagree with you. For CERTAIN kinds of optimization, I'll definitely agree with you. Things like algorithmic optimization can and should absolutely wait until the whole program is finished. Certain kinds of optimization, though, need to be accounted for from the start as part of the higher level design. Or example, the choice to use a formal graph representation of your data, or a specific database representation, or (to pick an example from 3D graphics) the kind of visibility determination algorithm you use, that has implications on the design of your entire program and IS something you should optimize for in the design from the very beginning, because changing that kind of thing at the end requires MAJOR refactoring. Just my two cents, but I think it's dangerous to say you should NEVER consider optimization until the end.
First off, if you have a problem with using external libraries, then you just won't get anywhere with a C/C++. They are VERY general purpose, and intentionally so, and the whole idea is that implementation specific things are supposed to be provided in libraries, rather than the core language. That said:
1. Boost is actually very easy to integrate for most of its features. A few (small handful) of its components require compilation, but the vast majority of them are template-based and header only. Meaning just include a header file and there you go, you're using boost. No extra compilation/installation required.
2. This kind of thing is GREAT for doing small scripts, but HORRIBLE for doing large complex applications where type safety can be VERY important for avoiding bugs. If all you ever do are small, quick, limited scripts, then you're absolutely right that you should avoid C++, that's certainly not what it was meant for, and not so much the domain of a strongly typed language. For things like the software that runs large financial institutions and whatnot, there's a reason code like that should be avoided at all costs.
3. I have trouble imagining a situation where a real garbage collector would ever be superior to an RAII model with shared smart pointers for stuff allocated on the heap, outside of plugging up a leaking legacy app. Maybe for very simple programs, but once you get non-trivial destructors (for example, with objects that lock system resources), then you start having to do manual memory management in your GC environment anyway, and end up with a horribly ugly conglomeration of "mixed metaphors" as it were. Smart pointers really give you the best of both worlds: deterministic destruction, without having to worry about manually releasing anything. It's just a matter of getting used to declaring a smart pointer wherever you would have a "type *name" instead. So yes, I'd argue they ARE a substitute for garbage collection in almost any situation.
4. Sorry to be blunt, but you should probably RTFA on this one. The problem is solved through "concepts," which is the part of the new specification which deals with this specifically. It's essentially a C++ implementation of the "design by contract" metaphor.
5. In this case "can be" equates to "do whatever you like and it'll be portable on all major general purpose computers, and who uses Ruby or Python on embedded platforms anyway?" If you are able to compile with GCC, which is the case for pretty much every computer/OS combination in existence, then you can count on it being pretty damn portable. If you are programming for something like an ATM or a set-top box, then you probably aren't going to be using a high level scripting language anyway.
6. Yeah, it can get ugly. Thankfully this will be largely fixed with the "auto" keyword in C++0x.
A sagely programmer once said: Perl, the only language that looks the same after being compiled.
Steve Jobs likes to provide his UIs the way Henry Ford liked to provide his cars. Any color you want, so long as it's black.