|
I'm not exactly a C++ Guru so someone please correct me if I'm wrong, but it all depends on the underlying implementation of the container. For example, when you add something to the front of a vector, the whole vector may need to be reallocated, which would cause any iterators to become invalid. But a list doesn't need to move any data about except for the data you are adding and removing from the list, so resizing it doesn't invalidate iterators. (Unless you remove the item your iterator is at) So no, there are no hard-and-fast rules on when your iterators become invalid. Or maybe I'm wrong, I am naught but an undergrad student after all.
|
# ? Jul 30, 2010 08:44 |
|
|
# ? Jun 7, 2024 23:42 |
|
The STL programmer's guide does, in fact, contain hard-and-fast rules for when STL container iterators become invalidated. Of course, you're probably not actually using STL, but I don't think the rules are any different between standard library containers and their STL counterparts.
|
# ? Jul 30, 2010 09:07 |
|
Ledneh posted:Running into a goofy bug with a find() call on a map causing a segfault and it's really aggravating, I'm kind of flailing hoping I have a screwed up iterator somewhere at this point How about a code snippet?
|
# ? Jul 30, 2010 12:28 |
|
Mustach posted:Are you using std::find() or the map's find() member function? If std::find(), unless you created the iterators, then modified the map, then called find (or are modifying it in another thread while calling find), the iterators will be valid. If you're using the member function, the only thing that would break that would be another thread modifying the map. The member function, and the app in question is single-threaded. We're utterly baffled. (I don't think I've ever actually used std::find(), now that I think about it.) Oh well, fresh eyes this morning, maybe we'll have better luck. And thanks for the link to the programmer's guide, I'll poke through that. (edit) As for a code snippet, maybe after I get to work, after I've taken another look.
|
# ? Jul 30, 2010 15:31 |
|
I never really dealt with the iterator rules before but while learning a lot more about the various containers that are available in STL, I found that those SGI documents for each container will mention something about it/how it blows up iterators. I guess that doesn't help though since you were looking for general rules of some kind. I'm going to dig up IDEs (minimally) (again). I'm trying to make something that's getting to be complicated enough that I would benefit from autocompletion for methods and class members generally, and making something that could take a good shot at finding and opening the code where something is declared for me. I am currently playing the grep game and opening a ton of emacs buffers to try to figure out just names of things and their prototypes. I could stick with emacs, but preferably if it has some solution to this kind of thing.
|
# ? Jul 30, 2010 18:50 |
|
Dooey posted:I'm not exactly a C++ Guru so someone please correct me if I'm wrong, but it all depends on the underlying implementation of the container. Here is an example: code:
BigRedDot fucked around with this message at 19:14 on Jul 30, 2010 |
# ? Jul 30, 2010 19:00 |
|
Rocko Bonaparte posted:I'm going to dig up IDEs (minimally) (again). I'm trying to make something that's getting to be complicated enough that I would benefit from autocompletion for methods and class members generally, and making something that could take a good shot at finding and opening the code where something is declared for me.
|
# ? Jul 30, 2010 19:04 |
|
BigRedDot posted:Which container operations invalidate iterators and under what circumstances is stipulated precisely in chapter 23 of the C++ standard. (Talking about C++98, of course.) Maybe I misinterpreted his question, but I thought he was looking for something more general, like: Inserting into any container will invalidate iterators, removing from any container wont, resizing any container wont, etc.
|
# ? Jul 30, 2010 19:10 |
|
Dooey posted:Maybe I misinterpreted his question, but I thought he was looking for something more general, like: Inserting into any container will invalidate iterators, removing from any container wont, resizing any container wont, etc. I edited to add something like that but you are too fast. Here's the best "rule of thumb" I have: AFAIK associative container iterators are the most robust, retaining valid iterators after insert operations, and only invalidating iterators to specifically erased elements. List iterators are also fairly robust in the same way although some operations like spice(...) will still invalidate list iterators. vector and deque iterators are the most fragile and are invalidated under pretty much any insertion or erasure. Edit: though tbh I do think looking up the actual concrete answer is better than rules of thumb. BigRedDot fucked around with this message at 19:20 on Jul 30, 2010 |
# ? Jul 30, 2010 19:15 |
|
Yeah I was looking for a general answer, though when I say that keep in mind that at the time I wasn't aware the volatility of different containers' iterators could be so variable. At least now I have somewhere I can look, so I got something out of this whole sordid mess. So thanks all! (for the curious, the broken map::find() turned out to be due to a far-flung heap clobber. I shoulda realized Rational Purify wouldn't necessarily be accurate ) [on a related note I want to find the bastard on this team who decreed 'boost shared pointers are too difficult to read and use, just manage memory properly' and punch him/her in the god drat crotch] Ciaphas fucked around with this message at 23:17 on Jul 30, 2010 |
# ? Jul 30, 2010 23:12 |
|
Hey I'm back with an ALL NEW QUESTION! We're writing an app that needs to perform a lot of case-insensitive (ASCII only, no unicode) string comparisons during processing. A LOT. Our current method of case-insensitive checking is something like 50 seconds out of a 500 second run under optimized-compiled code. So I thought I'd see if there was a more performance-oriented method of doing this that I could substitute in without a week's worth of effort. Right now we have an ICTraits class that inherits from char_traits. In it eq and lt are overridden to call std::tolower on the characters they're comparing before returning their equality; compare is overridden to loop through the characters and check equality as you'd expect using the overridden eq and lt.
|
# ? Aug 2, 2010 01:56 |
|
Ledneh posted:Hey I'm back with an ALL NEW QUESTION! Consider these in the order 3 -> 4 -> 5 -> 6 -> 2 -> 1. 1. Could you save work by canonicalizing the strings to lowercase and then doing memcmp-style comparisons afterwards? 2. Could you save work by precomputing a checksum of the canonicalized strings and first comparing those, and then comparing if the checksums are equal? (If you are comparing for equality.) 3. Look at the generated assembly code. Is it inlining tolower or the character equality functions? (If not, get that inlined and try again.) 4. What's with the char_traits crap? (Everything is crap.) How does just writing the function manually work? 5. Do you really need to do all those string comparisons? If your comparisons are from using some std::map or binary search through an array or something like that, you could use a more appropriate data structure that doesn't net you a (log(n))^2 comparison cost. Hash tables are faster, have you tried those? If you're sorting, how about building some trie for the purpose? It doesn't take a week to build a fast trie datastructure, only a few hours. 6. Is the cost in byte-by-byte string comparisons, or is it in something else, like the cache inefficiency of your algorithm? You might get more help if you tell use what goal requires all these string comparisons to happen.
|
# ? Aug 2, 2010 02:17 |
|
Are they just letters, or are there symbols too? Lowercasing a letter in ASCII is the same as bitwise or by 0x20, so you can do four-at-a-time by interpreting as an integer and doing bitwise or by 0x20202020, which might be marginally faster if your compiler isn't already doing it for you. Similarly, you can do four comparisons at once by reinterpreting as an integer and doing the comparisons that way, if your compiler isn't already doing it for you. memcmp does this and sometimes other tricks really well. But yeah, you're way better off giving us some way to help you avoid comparisons in the first place.
|
# ? Aug 2, 2010 02:23 |
|
I'll be able to provide more information once I'm back at work on Tuesday. I did forget to mention though that the char_traits thing works because that way we can do typedef basic_string<ICTraits> ICString and just use that instead of std::string. Long story short though, yes, we need to do the comparisons. There is literally no avoiding them. (edit) Straight-up alphanumeric strings, with underscores if the folks making the data are feeling posh. Ciaphas fucked around with this message at 02:26 on Aug 2, 2010 |
# ? Aug 2, 2010 02:23 |
|
Ledneh posted:Long story short though, yes, we need to do the comparisons. There is literally no avoiding them. You haven't explained what you're doing. Why do you refuse to tell us? You obviously don't want help.
|
# ? Aug 2, 2010 05:49 |
|
Eh? I just didn't think it was important, chill. We're reading in text files of about a gigabyte each, consisting of key-value pairs. We use the key/name to look up (currently in an oracle database) how to read and interpret the value (integer, float, literal string of fixed/variable length, hex characters to be reinterpreted as an int, a string to translate into a binary code, etc ad nauseum). Unfortunately no requirement for being consistent about case was ever established, and inertia means we have to take care of it. So we read in the key, call find on a map containing the data we've retrieved from the database (we've experimented with using boost::unordered_map too--not much help, at least according to the profiler), and use the value for getting the value read. (We just output these values in another format.) The profiler has pretty consistently told us that the call to std::tolower() for string comparison was taking the longest of anything else. Was that enough information? Ciaphas fucked around with this message at 06:23 on Aug 2, 2010 |
# ? Aug 2, 2010 06:20 |
|
So it sounds like you don't, in fact, need to call tolower in your string comparison operator because you could just lowercase the key before running any comparisons, which will save a lot of work. Similarly, is the in-memory map needed at all? If the information is already in a database, then just querying the database for each individual key may be significantly faster, especially if the database is local, as the people who wrote Oracle probably know a lot more about building intelligent indexes than you do.
|
# ? Aug 2, 2010 06:35 |
|
Also, isn't tolower locale-sensitive? Using a simple specialized inline version may be measurably faster if that's that hot. Edit #2: also, if you're using an std::map, you'll be doing a log number of comparisons, so you probably want to tolower once in advance. OddObserver fucked around with this message at 06:40 on Aug 2, 2010 |
# ? Aug 2, 2010 06:37 |
|
If C# counts, I'd like to ask a question please. I'm a first year Engineering student and we've been given the most ridiculous thing ever for a programming assignment. We're supposed to create a working version of Conway's Game of Life (http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) and I have no loving idea what to do. Right now, I'm trying to create the grid and somehow implement the MouseClick event handler in such a way that I can start filling in the grid with each click. That's all I want. Any ideas? I'm sure at least some of you have made this at some point and I just need a bit of direction.
|
# ? Aug 2, 2010 06:39 |
|
There's a .NET megathread, but we can maybe point you in the right direction. First of all, I don't see what is so ridiculous about this assignment. I'm pretty sure I had to do something similar when I was in my first year. What have you done so far? What are your data definitions? How are you representing the GoL game world? Have you exposed enough of an API to your game world class that you can update cells within it? Have you implemented the actual GoL yet? (that is, can you apply the rules to each cell and transform to the next state?) Can you draw the game state on your form?
|
# ? Aug 2, 2010 07:06 |
|
I hadn't considered looking up on the Oracle DB each time rather than preloading (and you are correct, it's local). I'll look into that on Tuesday. All the entries in the database are stored lowercase--that's no problem, we maintain it--it's just that the incoming data can be any case the provider pleases, so we have to lower-case the read-in keys each time. I haven't tired it, but wouldn't lowercasing the whole key then checking for string equality against the (already lowercase) map key amount to the same CPU load as lowercasing character by character (which we're doing now)?
|
# ? Aug 2, 2010 07:16 |
|
Ledneh posted:I haven't tired it, but wouldn't lowercasing the whole key then checking for string equality against the (already lowercase) map key amount to the same CPU load as lowercasing character by character (which we're doing now)?
|
# ? Aug 2, 2010 08:04 |
|
You could also get rid of all the std::tolower calls, replacing them with a string-lowering function that uses a static inline 256-byte lookup table or some simple thing that compiles to a conditional move to lowercase characters more efficiently, instead of some crazy locale thing (which probably boils down to a 256-byte lookup table inside a function call or two). I would try this, if you're spending all your time in the std::tolower function. You could also try using boost::unordered_map or whatever hash table implementation you want using a very cheap hash function, instead of a robust one. How big is the map? It is a std::map? Realize with all this effort you're only going to get a less than 10% speedup, since it's 50s out of 500. shrughes fucked around with this message at 08:33 on Aug 2, 2010 |
# ? Aug 2, 2010 08:31 |
|
shrughes beat me to it, but I'll say it anyways for emphasis: you're putting substantial effort towards a less-than-10% gain in speed. Maybe it's time to look at improving the algorithm itself. Of course, I don't know anything about the algorithm, but I will ask this: does each string in your file have anything to do with any other string in the file? If not, you could consider parallelizing this.
|
# ? Aug 2, 2010 15:26 |
|
Oh I know it's less than 10% and that performance shouldn't be a concern and all that. I'm just thinking things over over the weekend, and thought I'd ask, so no effort expended at all epswing, for some files how to interpret later values depends on values retrieved earlier in the file, so we (and by we I mean my predecessors) decided rather early on to forget about multithreading. I doubt the poor application would stand up to adding it in now. I already tried using unordered_map instead of map (in the last five minutes on Friday before I left ), to little effect, but then I didn't provide a hash function beyond the default for std::string either. Thanks all for all the thoughts and advice by the way, it's all much appreciated.
|
# ? Aug 2, 2010 18:08 |
|
Any resources on best practices regarding memory management for someone who rarely works in a language without an automatic garbage collector? Are there any pre-made solutions that will work out of box with code standardization or otherwise? I understand pointers and low-level memory storage and management well enough in theory, but I've never had to put anything into practice outside of academics to know more than the most common mistakes made. I'm concerned with memory leaks on a process that will be running 24/7 pretty much.
|
# ? Aug 3, 2010 09:47 |
|
Suppose I have two classes, A and B, and a function. Class B is a friend of class A, and the function is a friend of class B. Can the function access A's private members?
|
# ? Aug 3, 2010 11:49 |
|
No. Friendship isn't transitive.
|
# ? Aug 3, 2010 11:53 |
|
I'm friends with John, and John is friends with Fred. Can I tickle Fred's balls?
|
# ? Aug 3, 2010 12:04 |
|
Gotcha, thanks. Then is it possible to declare a function as a friend of two classes? Or should I rethink my class design?
|
# ? Aug 3, 2010 12:21 |
|
Yeah, you just declare it as a friend in both classes. (I'm assuming that the function takes A and B as arguments.) The more friends you add, the more likely it is that your class design is convoluted. What does the function do with the private data? Could you rewrite the function to just take the data that it needs as its arguments instead of A and B? Then it wouldn't need to be a friend.
|
# ? Aug 3, 2010 12:29 |
|
Mustach posted:Yeah, you just declare it as a friend in both classes. (I'm assuming that the function takes A and B as arguments.) I guess I should break down what I'm trying to do. I'm trying to implement a singly linked list. I have two classes: a class "node" which holds the data for each node and the functions to manage the node (constructors, stream operators etc), and a class "linklist" which holds a pointer to the first element as well as functions to manage the list (insertion, constructors etc). The function I'm having trouble with is an overloaded << operator for the linklist class. It needs to access the private node data to print it. Most of the examples I find online implement the node as a structure. Is this preferable?
|
# ? Aug 3, 2010 12:40 |
|
Adahn the nameless posted:I guess I should break down what I'm trying to do. I'm trying to implement a singly linked list. I have two classes: a class "node" which holds the data for each node and the functions to manage the node (constructors, stream operators etc), and a class "linklist" which holds a pointer to the first element as well as functions to manage the list (insertion, constructors etc). Are the nodes completely managed by the linked list and never touched by client code? If so, make Node a private nested class inside LinkedList.
|
# ? Aug 3, 2010 13:00 |
|
Flobbster posted:Are the nodes completely managed by the linked list and never touched by client code? If so, make Node a private nested class inside LinkedList. I had intended the client code to call the node constructors, but I can change that. Maybe have a function in the "linklist" class call the node constructor?
|
# ? Aug 3, 2010 13:27 |
|
Adahn the nameless posted:I had intended the client code to call the node constructors, but I can change that. Maybe have a function in the "linklist" class call the node constructor? The client of your linked list should not be touching a node class. The only thing the client should know is that it can put and remove items of the linked list. The linked list is responsible for each node construction. There are some interesting design patterns you could get into on how you construct nodes internally, but your client should never construct nodes.
|
# ? Aug 3, 2010 16:42 |
|
HFX posted:The client of your linked list should not be touching a node class. The only thing the client should know is that it can put and remove items of the linked list. So I should have a public function that creates and inserts the node in the linked list class call private functions in the node class? Could I transplant this same architecture to a template linked list class?
|
# ? Aug 3, 2010 18:09 |
|
baquerd posted:Any resources on best practices regarding memory management for someone who rarely works in a language without an automatic garbage collector? Are there any pre-made solutions that will work out of box with code standardization or otherwise? The best practice is to work in C++ and use RAII for *everything*. Boost has some excellent smart-pointer libraries, or if necessary you can roll your own, but if you don't use RAII then resource management is really complicated. In particular, if you're using exceptions and you're not using RAII then you are insane and wrong. If you're not using exceptions and not using RAII you are merely asking for a lot of trouble.
|
# ? Aug 3, 2010 18:42 |
|
I've got an ABNF spec for a protocol that is reasonably (but not extremely) complex. I need a decoder in straight C, but I haven't found something suitable in an existing library. Should I:
|
# ? Aug 3, 2010 21:10 |
|
Adahn the nameless posted:So I should have a public function that creates and inserts the node in the linked list class call private functions in the node class? Could I transplant this same architecture to a template linked list class? Yes and Yes. I'm trying to remember what books I used to recommend for C++. I think Ivor Hortons Visual C++ 6 was pretty good for learning the basics of C++ and Object Orientation (ignore second half of the book which is about MFC programming). I think there was an even better one, but it too would be done by Wrox. Once you have the basics, Professional C++ and the Bjarne Stroustrup book are worth reading. I think the Dietel & Dietel C and C++ book are good too (ignore the rest of their stuff). Anyway, what you want to learn to do with an object oriented language like C++ is to hide details that are uninteresting to client code. Learn to have single responsibility principles. Example: Your node class for a linked list only needs to know its neighbor(s) and what it is storing. Your list class needs to know how to store nodes to ensure correct placement and retrieve items out of those nodes when asked.
|
# ? Aug 3, 2010 21:15 |
|
|
# ? Jun 7, 2024 23:42 |
|
rjmccall posted:The best practice is to work in C++ and use RAII for *everything*. Boost has some excellent smart-pointer libraries, or if necessary you can roll your own, but if you don't use RAII then resource management is really complicated. Still wishing I could kick my coworkers in the junk for not letting me use shared_ptrs.
|
# ? Aug 3, 2010 23:46 |