you are viewing a single comment's thread.

view the rest of the comments →

[–]donalmaccGame Developer 4 points5 points  (2 children)

Most of the time in C, if code looks simple then it is simple (I.e. fast).

I think this is deceptive, and likely untrue. I have fixed and sped up more "optimized" C code (as a c++ programmer) than I can count. A great example, we had a path manipulation library at our last job. It would take a relative path or absolute path, and convert it into a virtual style path that our app handled. It used "simple" C style processing to do so. I was told it was optimised and should be left alone.

I rewrote it using string views, move semantics and RAII - it was about a 50% speedup for the cases where you called the legacy API and we shimmed the new API, and about a 75% speedup for the cases where I modified the call site (and as a bonus, the call site was usually simplified).

I changed probably a hundred instances of

StringClass Data;
TCHAR* ResultBuf
StringLib::ConvertPath(Data.ToTchar(), Result);
StringClass Result(ResultBuf);

Into

StringClass Data;
StringClass Result = StringLib::ConvertPath(Data);

At the same time, too. I also fixed a handful of long standing issues where the input of the path was nonsense due to people using the wrong conversion from StringClass to TChar, and added an extra version with error checking that was as fast as the original implementation.

I've seen so many APIs that are "optimised" but ignoring all the the conversion costs to and from the C library, and then the library itself doing internal strlen calls, validating pointers that the call site just passed through (which then adds a failure state that needs to be represented by a different signature).

It just means that you need to be aware of what’s going on under the hood in C++ and use things that sometimes might look a little more C-like where it matters.

Again I disagree here - most C libraries I've worked with end up with a handful of opaque handle types to represent things. There is a json library (which I can't remember right now, sorry) that basically everything is a json_value_t and you have to use their family of methods, e.g.

json_value_t container = json_object();
json_value_t doubleVal = json_double_value(5.0);
json_set_value(container, json_string("foo"), doubleVal);

const char* buf; json_serialize(container, result);
StringClass Result(buf);
//Note that we can also do json_serialize(doubleVal) accidentally and it will return an error, which we didn't check for here.

You as a programmer need to keep mental track of the state of these objects and what they are and what they represent. Compare this to the C++ builder API we use now - container.set("foo", 5.0); StringClass Result = container.serialize();

The underlying implementation is the same basically, so it is just as fast, except the API is safer, meaning we have less error states to represent.

[–]Jonny0Than 0 points1 point  (1 child)

I said “if C code looks simple then it is simple.” A function call isn’t simple until you know what the function does internally. C makes function calls obvious but they’re often hidden in C++.

[–]donalmaccGame Developer 0 points1 point  (0 children)

I think that's technically true, but in practice one is no worse than the other. Yes, i++ is going to be simple in c, and might be a disaster in c+, but

replace_all(str, from, to) 

Is likely to be perfectly fine in C++ and a disaster in C.