wrl@apple.com (Wayne Loofbourrow) (09/30/89)
I'm relatively new to C++, but am very used to C. I'd like to dive in and write programs in an object oriented fashion, but am concerned about efficiency. Ideally, efficiency concerns would not effect the design of the interface to a class, but only its implementation. However, here is a case in point where it seems to. Does anyone know of a better way? Here's the situation: People seem to have no trouble defining operators like this: complex operator+(complex c1, complex c2) { return complex(c1.re + c2.re, c1.im + c2.im); } ...and using it like this: complex a,b,c; // ... a = b + c; One might be concerned about the creation of a temporary inside the function, a copy to a temporary outside the function, and an explicit copy into a. However, complex objects are fairly fast to copy and create so why worry? Besides inlining would help. Ok. But now lets say you've got a more complicated beast with lots of pointers chaining off of it. For example, a graph object implemented with various linked lists (say vertex lists). Now, to be consistent with the way complex objects work, I want assignment to make a copy of the graph. That way I can modify the original without affecting the copy. So then I write: graph operator+(graph g1, graph g2) { graph t; // compute t from g1 and g2. return t; } This might compute a new graph that is the union of the two. But now, when I say: graph a,b,c; // compute b and c a = b + c; All sorts of copying is going on, and each time an entire graph is created (zillions of allocations and all). From what I can tell, the best I can hope to do is: inline graph operator+(const graph& g1, const graph& g2) // ... same as before which will still involve copying of large objects (from the temporary created in computing (b+c) into a). A possible solution is to define either: void graph::operator+=(const graph& g) or void addgraph(graph& a, const graph& b, const graph& c) but either of these are awkward to use and preclude using the add operation in expressions. Anyone have a good way get what I want?: ...convenient (b+c) style notation but without the copying inefficiency. Wayne Loofbourrow Advanced Technology Group Internet: wrl@apple.com
ttwang@polyslo.CalPoly.EDU (Thomas Wang) (09/30/89)
wrl@apple.com (Wayne Loofbourrow) writes: >Ok. But now lets say you've got a more complicated beast with >lots of pointers chaining off of it. For example, a graph object >implemented with various linked lists (say vertex lists). >graph a,b,c; >// compute b and c >a = b + c; >All sorts of copying is going on, and each time an entire graph is >created (zillions of allocations and all). When you have BIG objects it makes sense to have a 'handle' class which manages copying. The 'handle' class would be very small, and contains a real pointer to the 'graph' object. So when a handle_graph object get copied, it takes very small CPU time. Then you make all the functions to operate with the handle class. class handle_graph { graph* real_ptr; int ref_count; public: graph* ptr() { return real_ptr; } ptrcopy(handle_graph&, handle_graph&); fieldcopy(handle_graph&, handle_graph&); }; This is reference counting. With a set of class templates, the handle definition can be generated semi-automatically. I am in the process of writing such a beast. >Wayne Loofbourrow -Thomas Wang ("This is a fantastic comedy that Ataru and his wife Lum, an invader from space, cause excitement involving their neighbors." - from a badly translated Urusei Yatsura poster) ttwang@polyslo.calpoly.edu