|
|
|
|
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Or rather, a tale of two IDEs for two programming languages.
Yesterday I downloaded and installed Visual C++ 2010 Express. (Can you
guess which language that's for?) The installation takes /forever/. It's
one of those programs where you "download the installer" and get a 20KB
file that just runs the downloader for the /real/ installation program.
(Why the **** do people do that?!) Still, at least once it's installed,
it runs fairly fast.
In common with all known IDEs, hitting the "new project" button creates
a project with /way/ more useless boilerplate code than you will ever
need. I mean, it creates about half a dozen source files - two separate
C++ files, three header files, etc. Which is completely overkill just
for implementing Hello World. (It also sets the tab depth to something
like 18 spaces or something equally absurd.)
My C++ is very rusty. Hell, I wasn't even that good in the first place!
But deleting all the unwanted files and starting again from scratch, I
was able to implement Hello World from memory without needing to look
anything up. So that's a good start.
Now for my next trick, a Huffman encoder. In most languages it's
trivially easy to implement, and yet it uses a surprising amount of
language features. And, uh, yeah... I can't implement this. It's the
damnedest thing, I swear I already wrote this code once... but I can't
find it anywhere, so maybe I'm imagining it.
Anyway, C++ employs a manual memory management model. Surprisingly, if
you can get away with using only STL containers, you don't have to know
or care that this is the case. All that template magic neatly takes care
of the problem for you. And that's great.
I made all the usual beginner's stupid mistakes - e.g., passing data
structures by value, and then wondering why my alterations aren't
visible from outside the function. (Most OO languages default to passing
by reference. But then, most OO languages provide automatic memory
management too...)
The real sticking point was when I started trying to use abstract
classes. It seems that you cannot have a variable of an abstract class.
(Because creating that variable would require creating an instance of an
abstract class, which is illegal.) You can only have a variable that
/points to/ such a value. (Because then what it points to can actually
be some concrete subclass.)
That's all fine and logical and everything, but there's a nasty snag:
Now you have to care about memory management. And there's no way around it.
I was eventually able to get the program to produce the correct output.
However, it uses the dreaded "new" operator. In particular, it does
/not/ use the "delete" operator anywhere. In other words, it leaks. I
have literally no idea how to fix this. I can't think of any way of
doing it that won't result in double-freeing objects. That's mainly
because I can't put responsibility for object creation (and hence object
destruction) in the logical place. And /that/ is because I don't have
some of the necessary technical understanding.
I found a reasonable C++ introduction at cplusplus.com, but it doesn't
explain several technical points which I'm unclear on. Does anybody know
of a better resource? (Obviously, a Google search will turn up millions
of results. It's hard to know which ones are /good/ resources, however.)
Having spent a few hours on that, I decided to turn my attention to
Java. Now I've coded fairly extensively in Java in the past, but that
was about 10 years ago. (Jesus Christ I'm old now! >_< ) I still
remember most of the syntax, but I haven't actually tried to /compile/
any code for a very long time. I'm not sure if I'll remember how...
So I downloaded the NetBeans IDE for Java SE. Which immediately told me
that I have to install the Java SE JDK before running the installer.
Gee, thanks for that. :-P You couldn't have made that clearer from the
download page, no?
So, 80MB for NetBeans, another 80MB for the JDK itself, and finally I'm
in business. Now, I'm not saying NetBeans is /inefficient/, but
swallowing 200MB of RAM just because I double-clicked the icon to open
the IDE does seem /just a tad excessive/ to me. Initially I was just
trying to figure out how to work the thing, but as I started to learn my
way around and started trying to actually /do/ stuff, the IDE seemed
unacceptably unresponsive. (Quite apart from visually /looking/ like
something baked by an open source committee rather than being a polished
commercial product.)
Like VS, asking NetBeans for a basic project generates a plateful of
useless code that you then have to waste time deleting. (Apparently
there's an Ant script somewhere too... whatever the hell that is.) It
also sets the tab depth far, far too deep. But unlike VS, it also seems
to /insist/ on incorrectly putting the open bracket on the same line as
the declaration it begins. (This incorrect practise is also common in
C++, and yet I didn't seem to have this problem with VS.) It's easy
enough to manually fix, I suppose.
While VS does syntax highlighting and occasionally pops up a list of
method names or something (usually a few seconds too late to be useful,
or using out of date type information), NetBeans seems a little more
impressive. Oh, it still does syntax highlighting. (With some rather
unhelpful colour choices.) And it still pops up out-of-date method lists
that actually get in the way far more than they help. But it goes a few
steps further.
For example, Java is such a retarded language that the only way to copy
some stuff from one array to another is to manually write a loop. So I
wrote a loop. And a little box popped up saying "manual array copy
detected - replace with System.arraycopy()?" I clicked the button. All
the temporary variables vanished, and were replaced with the above
method call, with the correct source and destination, and even the
correct array indices. I'm impressed.
Or rather, I'm impressed at the IDE. Implementing array copying as a
static method on a general utility class? Yeah, /that/ sounds like
fantastic OO library design! :-P Really, Java? I mean, really? Still, at
least you don't need to use an abstract factory factory to use it. The
syntax is quite straight forward.
Also interesting is that when you call a method, it seems to take a
guess at what variables currently in scope are of the correct type, and
fills that in for you automatically. Handy when it works, mildly
irritating when it doesn't.
Needless to say, Hello World was no challenge at all. Implementing my
Huffman encoder was a little more tricky. When I ran it, I got a null
pointer exception. Amusingly [or not], it is apparently impossible to
make the IDE halt the program at the location where the exception is
thrown. Even in debug mode, it just runs the program, prints out the
exception, and then quits. No way of, you know, inspecting the program
state at the moment of the exception to actually see what the problem
is, or anything like that. In fact, come to mention it, I can't find any
way at all to single-step through the program. VS did all of this and
more. :-P
As always with these types of problems, I eventually discovered that I'd
forgotten to initialise something in the code. (An empty array is of
course /not/ the same thing as a null pointer...) Once I fixed that, it
all worked just fine. If I had had access to a debugger that would
actually tell me which field it was that was uninitialised, it would
have taken seconds to figure out the problem and fix it. It only took
half an hour because I had to sprinkle print() all over the place until
the problem became apparent.
So there we are. I doubt I'd remember much about the AWT (although,
didn't they deprecate that in favour of Swing?), but I can certainly
still write algorithmic code in Java without much ado. Maybe today I'll
try something more ambitious with it. If I can avoid throwing the IDE
out of a window.
(Is it just me? "Net Beans"? It's an IDE. What the /hell/ does that have
to do with networking? The "beans" part I kinda get; everything
Java-related has to be themed on coffee or coffee beans. But why "net"?)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 3/13/2012 6:11 AM, Invisible wrote:
> I was eventually able to get the program to produce the correct output.
> However, it uses the dreaded "new" operator. In particular, it does
> /not/ use the "delete" operator anywhere. In other words, it leaks. I
> have literally no idea how to fix this. I can't think of any way of
> doing it that won't result in double-freeing objects. That's mainly
> because I can't put responsibility for object creation (and hence object
> destruction) in the logical place. And /that/ is because I don't have
> some of the necessary technical understanding.
>
> I found a reasonable C++ introduction at cplusplus.com, but it doesn't
> explain several technical points which I'm unclear on. Does anybody know
> of a better resource? (Obviously, a Google search will turn up millions
> of results. It's hard to know which ones are /good/ resources, however.)
Good memory management in C and C++ are things you really have to learn
as you go along. You can probably encapsulate your heap object pointers
into a handler class, but you probably have some learning to go before
you're ready to implement that.
I think the best way to go is to decide whether a given pointer
represents an object that is created on the heap and is owned by the
pointer's container, or if it just refers to an object that is owned by
some other container. The owner takes care of deleting its objects
created on the heap, but otherwise objects get left alone.
> (Is it just me? "Net Beans"? It's an IDE. What the /hell/ does that have
> to do with networking? The "beans" part I kinda get; everything
> Java-related has to be themed on coffee or coffee beans. But why "net"?)
Apparently Java's developers are focused on its Web capabilities, and
are trying to emphasize that.
Regards,
John
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 13/03/2012 11:33 AM, John VanSickle wrote:
> On 3/13/2012 6:11 AM, Invisible wrote:
>
>> I was eventually able to get the program to produce the correct output.
>> However, it uses the dreaded "new" operator. In particular, it does
>> /not/ use the "delete" operator anywhere. In other words, it leaks.
>
> Good memory management in C and C++ are things you really have to learn
> as you go along. You can probably encapsulate your heap object pointers
> into a handler class, but you probably have some learning to go before
> you're ready to implement that.
>
> I think the best way to go is to decide whether a given pointer
> represents an object that is created on the heap and is owned by the
> pointer's container, or if it just refers to an object that is owned by
> some other container. The owner takes care of deleting its objects
> created on the heap, but otherwise objects get left alone.
Sure. I get all that. The problems I'm facing are technical, not
theoretical. I know what code I want to write, but I don't know how to
use the language features to write that code.
>> (Is it just me? "Net Beans"? It's an IDE. What the /hell/ does that have
>> to do with networking? The "beans" part I kinda get; everything
>> Java-related has to be themed on coffee or coffee beans. But why "net"?)
>
> Apparently Java's developers are focused on its Web capabilities, and
> are trying to emphasize that.
By sticking "net" in the name? Heh, that's like inventing a scripting
language and naming it after Java to try and latch onto its
popularity... Oh, wait. Somebody did that. :-P
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 13/03/2012 10:11 AM, Invisible wrote:
> So, 80MB for NetBeans, another 80MB for the JDK itself, and finally I'm
> in business. Now, I'm not saying NetBeans is /inefficient/, but
> swallowing 200MB of RAM just because I double-clicked the icon to open
> the IDE does seem /just a tad excessive/ to me. Initially I was just
> trying to figure out how to work the thing, but as I started to learn my
> way around and started trying to actually /do/ stuff, the IDE seemed
> unacceptably unresponsive. (Quite apart from visually /looking/ like
> something baked by an open source committee rather than being a polished
> commercial product.)
I eventually gave up with NetBeans. It's just too cripplingly slow. (I
did not have this problem with VS.) If I type something and have to wait
/4 seconds/ for anything to appear on the screen, that's too slow, IMHO.
Seriously. Once I got to a handful of files, amounting to a grand total
of 6KB of Java source, performance became unacceptably poor. I also love
the way that running the program randomly fails from time to time. You
click "run", and it says "build successful", followed by "cannot find
compiled code". But if you click the button enough times, eventually it
runs perfectly. So... WTF is wrong with it?!
In all, I was spending /far/ too much time fighting the IDE and not
enough time actually coding stuff. So I switched back to a text editor
and a command prompt. (Amusing how installing the JDK doesn't add any of
the Java binaries to the search path. If by "amusing" you mean "tedious
and annoying"...)
Some of you may remember that logic simulator I built in Haskell a while
back. If I recall, I challenged Warp to implement it in C++, and he
couldn't even figure out how the heck it works. (I must admit, it's a
loopy piece of coding.) Perhaps a Java implementation will be less
mind-bending for any curious souls - or perhaps not, IDK. Either way,
it'll be a while before *I* can implement it in C++. (!)
Also, I think I might have to build a parser for Java. Because, damnit,
writing stuff like
new Or(new And(new Equals(new NameVar("x"), new IntegerConst(1)), new
Equals(new NameVar("y"), new IntegerConst(2))), ...
becomes tedious /rapidly/!
I keep hearing that Java has added generics since I last worked with it.
I find it amusing that we can now write HashMap<Foo, Bar>, and yet we
have type signatures like
public Object get(Object key);
Really? I mean, really? Should that not be
public V get(K key);
or similar? Is that not the entire /point/ of generics?
Then we have fun such as Object.clone(), which is [still] defined to
return Object. So you get to write stuff like
java.util.HashMap<Variable, Expression> copy =
(java.util.MashMap<Variable, Expression>) old.clone();
And of course, no way to define type aliases (and no automatic type
inference either), so if I decide to change the HashMap for, I don't
know, a TreeMap perhaps, I'm going to have to change type signatures in
a dozen places. Gee, thanks for that. :-P
Even more fun, apparently writing the above code is an "unsafe,
unchecked construct" - or so the compiler warns me with /every single
damned compile/. Despite the fact that the above is statically
guaranteed to always work. *sigh*
Yes, Java /still/ sucks. :-P
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 13/03/2012 03:15 PM, Invisible wrote:
> I keep hearing that Java has added generics since I last worked with it.
> I find it amusing that we can now write HashMap<Foo, Bar>, and yet we
> have type signatures like
>
> public Object get(Object key);
>
> Really? I mean, really? Should that not be
>
> public V get(K key);
>
> or similar? Is that not the entire /point/ of generics?
Interesting fact: It seems the latest JDK implements /two/ versions of
the same interface.
public interface Iterator
{
public boolean hasNext();
public Object next();
public void remove();
}
public interface Iterator<E>
{
public boolean hasNext();
public E next();
public void remove();
}
If you accidentally forget to mention the element type, you get the old
version of the interface, with all its type unsafety. Isn't that great?
*sigh*
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Invisible <voi### [at] devnull> wrote:
> In common with all known IDEs, hitting the "new project" button creates
> a project with /way/ more useless boilerplate code than you will ever
> need.
Probably because you created a new *Windows* project, rather than a
portabla command-line one.
> The real sticking point was when I started trying to use abstract
> classes. It seems that you cannot have a variable of an abstract class.
> (Because creating that variable would require creating an instance of an
> abstract class, which is illegal.) You can only have a variable that
> /points to/ such a value. (Because then what it points to can actually
> be some concrete subclass.)
Dynamic binding, abstract classes, and even inheritance, are needed
in practice significantly less often than one might think (especially
if one comes from a background where that's basically the only way of
doing anything).
In quite many cases it's enough to have classes with no dynamic binding
nor inheritance, and which are handled by value (at least if they contain
only moderate amount of data). In the case of a huffman coder, I really
don't understand what do you need abstract classes for. (There *is* such
a thing as over-designing, when talking about OOP.)
In many cases if you design your program such that you don't need
dynamic binding, your program will often become more efficient in terms
of both speed and memory usage. (Not because dynamic binding would be
inefficient, as it isn't, but because dynamic memory allocation is, and
if we are talking about abstract classes, then dynamic memory allocation
usually goes hand in hand with it.)
(Inheritance in itsef is not bad in this sense, because C++ does not
force dynamic binding. Base classes can sometimes be used to group common
implementations into a single module, to avoid code repetition. Using an
inherited class is in no way less efficient than one that has no parent
class at all. However, as said, even inheritance is less often necessary
in practice than one might think.)
> I was eventually able to get the program to produce the correct output.
> However, it uses the dreaded "new" operator. In particular, it does
> /not/ use the "delete" operator anywhere. In other words, it leaks. I
> have literally no idea how to fix this. I can't think of any way of
> doing it that won't result in double-freeing objects. That's mainly
> because I can't put responsibility for object creation (and hence object
> destruction) in the logical place. And /that/ is because I don't have
> some of the necessary technical understanding.
If you are an experienced, competent c++ programmer, each time you have
to write the dreaded keyword 'new', it should give you a feeling of unease,
and the instinctive desire to think of better alternatives. This even if
you have no problems whatsoever with memory management in this situation
(eg. because you are using a smart pointer). That's because 'new' is not
only a source of leaks, but also it's inefficient.
There are, of course, situations where 'new' is the only and best
solution. For example, if you are implementing your own dynamic array
(which has something that std::vector does not provide), then there's
no problem. However, the usage of 'new' should in this case be tightly
restricted to happen inside this dynamic array class, strictly controlled
by it. Maximum encapsulation of the memory management is the key.
If, for some strange reason, you need to allocate individual objects
dynamically with 'new', then you should either use a smart pointer to
handle it (C++11 provides std::unique_ptr and std::shared_ptr for this
purpose), or you should write a class that acts as such (in other words,
which acts kind of like a data container containing one element: The
allocated object.)
Writing 'new' outside of a class member function (of a class that handles
that allocated memory, of course) is always a risk. Even if you make sure
there's a corresponding 'delete' at the end of the function, your code
will not be exception-safe (because if an exception happens before that
'delete', the allocated object will be leaked; the exception is if you
use a smart pointer such as std::unique_ptr to handle it).
In practice I don't remember having to write 'new' even once outside
of a class that handles the allocated memory. Smart pointers are fine
and all, but they are seldom needed in practice.
Now, writing a class that properly manages its dynamically allocated
memory is a non-trivial task of its own.
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 13/03/2012 03:56 PM, Warp wrote:
> Invisible<voi### [at] devnull> wrote:
>> In common with all known IDEs, hitting the "new project" button creates
>> a project with /way/ more useless boilerplate code than you will ever
>> need.
>
> Probably because you created a new *Windows* project, rather than a
> portabla command-line one.
Nope. I specifically requested "console application".
> Dynamic binding, abstract classes, and even inheritance, are needed
> in practice significantly less often than one might think (especially
> if one comes from a background where that's basically the only way of
> doing anything).
Perhaps. Although in a sense, I'm not actually "interested" in building
a specific application here, I'm interested in figuring out how
inheritance and so forth actually works in C++.
> In the case of a huffman coder, I really
> don't understand what do you need abstract classes for. (There *is* such
> a thing as over-designing, when talking about OOP.)
The most obvious way to implement this is to physically build a binary
tree. That requires either inheritance, or else doing something sly with
unions. (Or even being /really/ dirty and just having one node type, and
ignoring the unused fields.)
Now for the /encoding/ part itself, I don't actually need a physical
tree. I have a vague recollection that last time I did this, I ended up
cheating and just storing a vector of codewords, and manually munging
that. It's a lot less elegant, but avoids dynamic allocation. (Or
rather, no it doesn't, but it hides it in STL containers, so you don't
have to do it manually.)
This application is just supposed to be the "warm up" for my next
project, which will involve building complex expression trees. I really
don't see how you can get away with no dynamic binding when each node
type needs to be processed differently. Unless you go all non-OO and try
to implement node type dispatch manually...
> In many cases if you design your program such that you don't need
> dynamic binding, your program will often become more efficient in terms
> of both speed and memory usage.
I guess to some extent it depends on whether your goals are efficiency
or maintainability. Certainly the code I'm trying to write will probably
take milliseconds to execute, whichever way I implement it. If I was
writing something high-performance, I might care about such things.
> If you are an experienced, competent c++ programmer, each time you have
> to write the dreaded keyword 'new', it should give you a feeling of unease,
> and the instinctive desire to think of better alternatives.
Well, I did try to think of a way around it. But I failed to come up
with a solution.
> There are, of course, situations where 'new' is the only and best
> solution. For example, if you are implementing your own dynamic array
> (which has something that std::vector does not provide), then there's
> no problem. However, the usage of 'new' should in this case be tightly
> restricted to happen inside this dynamic array class, strictly controlled
> by it. Maximum encapsulation of the memory management is the key.
The problem is, I want to copy some data, but since I don't know what
class it belongs to, I have no idea how big it will be. Presumably
there's some way around that, but damned if I know what it is... Like I
say, I need to find a more thorough reading resource that explains this
stuff properly.
> Now, writing a class that properly manages its dynamically allocated
> memory is a non-trivial task of its own.
Is that not just a case of allocating the memory correctly in the
constructor, and freeing it properly in the destructor? (I mean,
assuming nobody tries to copy the object or free its dynamic memory or
anything like that...)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Invisible <voi### [at] devnull> wrote:
> > In the case of a huffman coder, I really
> > don't understand what do you need abstract classes for. (There *is* such
> > a thing as over-designing, when talking about OOP.)
> The most obvious way to implement this is to physically build a binary
> tree. That requires either inheritance, or else doing something sly with
> unions. (Or even being /really/ dirty and just having one node type, and
> ignoring the unused fields.)
I don't see why you need different types of objects for such a binary
tree. Each object can be identical to each other in structure. (If in
some nodes some of the fields are unused, so what? It will still be
significantly more efficient than dynamic binding.)
You don't need to mess with unions unless you really, really need to
make the objects as small as physically possible. However, making them
that small is completely moot if you are going to allocate them
individually anyways (the allocation bookkeeping overhead will nullify
any space saving you could get from shaving off a few bytes using unions.)
It would only make a significant difference if you used arrays of
objects as your tree data structure, rather than allocating objects
individually, and there were tons and tons of elements.
> Now for the /encoding/ part itself, I don't actually need a physical
> tree. I have a vague recollection that last time I did this, I ended up
> cheating and just storing a vector of codewords, and manually munging
> that. It's a lot less elegant, but avoids dynamic allocation. (Or
> rather, no it doesn't, but it hides it in STL containers, so you don't
> have to do it manually.)
Using an array of objects (rather than individually allocated objects)
doesn't completely avoid memory allocation, but it minimizes their amount,
which is often very significant. (In other words, if your program makes
20 allocations instead of a million, it will have a significant impact
on the speed of the program.)
> This application is just supposed to be the "warm up" for my next
> project, which will involve building complex expression trees. I really
> don't see how you can get away with no dynamic binding when each node
> type needs to be processed differently. Unless you go all non-OO and try
> to implement node type dispatch manually...
If you really must have nodes of differing types, then it will become
complicated from the point of view of memory management. Lack of garbage
collection can be a b**** sometimes. (Not that it's impossible; it just
requires a lot of care and strict coding practices to get it right. This
is something you usually want to avoid altogether, if possible.)
Of course your nodes could simply be (smart) pointers of a base class
type, but then you will be making twice as many allocations (because for
each node you will be allocating the node itself, which is a smart pointer,
*and* the object that the node is pointing to), which is even worse from
an efficiency point of view. It becomes simpler like this, but don't expect
extreme speed. (Haskell probably would beat C++ in this situation.)
It's sometimes quite a bummer, but when writing efficient C++ you have
to always think "how many memory allocations will this perform?" (even,
and especially, when using STL data containers). The less individual
memory allocations are done, the better. (But of course that's not the
only thing that affects speed, but it's the one major thing not related
to the algorithm itself that does.)
I have to grant that languages like Java are better at this because
there you don't have to worry about how many allocations are performed
(as JVM's have a significantly faster memory allocation than the C/C++
runtime.)
> > In many cases if you design your program such that you don't need
> > dynamic binding, your program will often become more efficient in terms
> > of both speed and memory usage.
> I guess to some extent it depends on whether your goals are efficiency
> or maintainability.
Avoiding dynamic binding does not automatically mean that your program
becomes more complicated and harder to maintain. In fact, it can sometimes
mean the opposite. Sometimes your programs actually become *simpler* and
much easier to understand. Full OOP (beyond simple encapsulation using
classes) is not always the universal panacea for clarity and maintainability.
(Of course this depends on each individual case.)
> Certainly the code I'm trying to write will probably
> take milliseconds to execute, whichever way I implement it. If I was
> writing something high-performance, I might care about such things.
But even then you have to think which design is easiest in terms of
memory management. The less you have to manage memory manually, the
better. Your program becomes safer and simpler.
> The problem is, I want to copy some data, but since I don't know what
> class it belongs to, I have no idea how big it will be.
I didn't understand your problem from that description alone.
> > Now, writing a class that properly manages its dynamically allocated
> > memory is a non-trivial task of its own.
> Is that not just a case of allocating the memory correctly in the
> constructor, and freeing it properly in the destructor? (I mean,
> assuming nobody tries to copy the object or free its dynamic memory or
> anything like that...)
The simplest design is to delete the allocated memory in the destructor
(it doesn't really matter where inside the class the memory is allocated
as long as the pointer is kept as 0 when there's nothing allocated) and
then disabling the copy constructor and assignment operators. (In C++98
this is done by declaring them private and not implementing them. In C++11
you can explicitly express this with a keyword.)
Often this is enough. However, sometimes you would want to be able
to copy and assign objects of that class type around. That's where the
non-triviality kicks in.
The first problem is: How should the object be copied? There are many
possibilities:
- Perform a deep copy. Every time the object is copied or assigned, all
of the data it's managing is copied. This is the easiest way of managing
copying, but it can be pretty inefficient with large amounts of data (and
because each time you make a copy you need an additional 'new').
- Make the class act as a reference to the managed data, in which case each
copy *shares* the managed data. In this case you need to use reference
counting to know when to delete the data. You also have to design your
program taking into account that the object is acting as a reference to
the data, not as the data itself. (This can work pretty well if your
data object is considered immutable.)
- Perform lazy copying. In other words, copying/assigning the object does
not yet deep-copy the data. Only when the data is modified it will be
copied if it was being shared between more than one object. This makes
copying and assigning more efficient, but accessors less.
- The data is *moved* from the original to the copy. This is very efficient
(because you don't need reference counting or anything else) but can be
quite limiting (because you are not actually copying anything, just moving
the data from one object to another).
The second problem is that implementing these is not completely trivial
and requires attention to detail and knowing the traps.
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Warp <war### [at] tagpovrayorg> wrote:
> The first problem is: How should the object be copied? There are many
> possibilities:
If you are wondering which solution the STL data containers use,
it's usually just a simple deep-copy whenever the container is copied
or assigned. (While this is implementation-defined, you can assume that
the vast majority, if not all, of the STL implementations out there use
deep copying.) You should take this into account when using the STL.
(In other words, never needlessly copy/assign a large data container.)
As said, deep-copying is the easiest/simplest solution in terms of
memory management, but you have to be careful to not be copying them
around without a good reason.
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Invisible escreveu:
> On 13/03/2012 10:11 AM, Invisible wrote:
> I eventually gave up with NetBeans. It's just too cripplingly slow. (I
> did not have this problem with VS.) If I type something and have to wait
> /4 seconds/ for anything to appear on the screen, that's too slow, IMHO.
ah, children from the 90's...
> Seriously. Once I got to a handful of files, amounting to a grand total
> of 6KB of Java source, performance became unacceptably poor.
That's not my (ackowledged little) experience. And surely not of most
people working on some hairy shared projects.
> In all, I was spending /far/ too much time fighting the IDE and not
> enough time actually coding stuff.
cool, now you'll be just fighting a wholesomely stupid language.
*oh, I felt so Darrenish now*
> Some of you may remember that logic simulator I built in Haskell a while
> back. If I recall, I challenged Warp to implement it in C++, and he
> couldn't even figure out how the heck it works.
Perhaps you should have told him what the code is supposed to do rather
than expect someone to figure out what some haskell code is doing.
Here's a challenge for you. What do these haskell snippets are supposed
to do?
snippet 1:
((.)$(.))
snippet 2:
f >>= a . b . c =<< g
and for a bonus, guess what this one does:
import System.Environment
foo n = 0 % (0 # (1,0,1)) where
i%ds
| i >= n = []
| True = (concat h ++ "\t:" ++ show j ++ "\n") ++ j%t
where k = i+10; j = min n k
(h,t) | k > n = (take (n`mod`10) ds ++ replicate (k-n) " ",[])
| True = splitAt 10 ds
j # s | n>a || r+n>=d = k # t
| True = show q : k # (n*10,(a-(q*d))*10,d)
where k = j+1; t@(n,a,d)=k&s; (q,r)=(n*3+a)`divMod`d
j&(n,a,d) = (n*j,(a+n*2)*y,d*y) where y=(j*2+1)
main = putStr.foo.read.head =<< getArgs
no googling, huh? ;)
> Yes, Java /still/ sucks. :-P
Yes and that is a feature by design.
What doesn't suck is the JVM and the tens of thousands of useful libs
that run atop it. It's the only truly cross-platform performant VM out
there. Think about it, libs you don't actually need to recompile on
your machine.
And if you don't like java, you can just choose from many languages
running atop it and leveraging from said libs: Scala, Jython, JRuby,
even quite a few Scheme implementations... any haskell work on this front?
BTW, Ant is yet another example of XML-madness: it's basically a
verbose XML makefile for java.
--
a game sig: http://tinyurl.com/d3rxz9
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|