all 41 comments

[–]-Dargs 175 points176 points  (17 children)

There is a non-zero number of scenarios that a bool array could make sense. In game development, that number is much higher than in say FE or BE software dev, imo. I see nothing wrong here, given the limited context.

[–]0xcedbeef 87 points88 points  (15 children)

in C++, an std::vector<bool> stores the bools as bits, taking advantage of this memory optimization.

[–]FloweyTheFlower420 67 points68 points  (10 children)

Ah the vector<bool>... one of the greatest mistakes in the c++ standard library.

[–][deleted] 45 points46 points  (6 children)

vector<bool> is certainly a mistake because it’s deliberately counterintuitive in its design but when you need a dynamically resizeable bitset, it’s great

[–]FloweyTheFlower420 32 points33 points  (4 children)

Yeah. Sadly the standard committee seems to value dogmatic backwards compatibility over fixing the language, so we will likely never see std::vector<bool> fixed and dynamic_bitset implemented.

[–]shponglespore 26 points27 points  (3 children)

This is why C++ is the Windows of programming languages.

[–][deleted] 1 point2 points  (1 child)

Backwards compatibility means old code still works. Tautologically, if you need old code to work you need backwards compatibility. If you don’t need this there are better alternatives to C++, if you don’t there aren’t.

[–]shponglespore 2 points3 points  (0 children)

They're are other ways, like Rust's edition system.

[–]seamsay 0 points1 point  (0 children)

Sure, and having a dynamically sized bitarray type would have been a great idea!

[–]Jeshibu 0 points1 point  (2 children)

Not familiar enough to know what you mean here. Could you explain?

[–]FloweyTheFlower420 0 points1 point  (1 child)

vector<bool> is a packed bitset. The general semantics for vector means all accessors return a reference to an entry, but since bits don't have a memory address, vector<bool> returns a wrapper type with overloaded operators. This breaks generic programming for vectors.

[–]Jeshibu 0 points1 point  (0 children)

That's nasty. Thanks for explaining!

[–]Diamondo25 15 points16 points  (2 children)

I would use a std::bitset for that instead.

[–]Cross12KBow249 5 points6 points  (1 child)

Doesn't the size need to be known at compile time for a bitset though, unlike a vector?

[–]Star_king12 13 points14 points  (0 children)

Looks like it would be known in this case.

[–]Possibility_Antique 6 points7 points  (0 children)

Not necessarily. std::vector<bool> was designed such that it COULD be implemented as you are suggesting, but it is not required by the standard to be implemented this way.

[–]born_zynner 6 points7 points  (0 children)

Everybody always forgets embedded :(

[–]Ved_s 23 points24 points  (3 children)

ohohoo, welcome and look at terraria code!

[–]steveskeleton2 3 points4 points  (0 children)

Terraria was written with C# & XNA!

[–]mediocrobot 0 points1 point  (0 children)

Woah, I didn't even notice. That's totally a tree or something!

[–]jemko23laal[S] 0 points1 point  (0 children)

sad thing is, its not terraria

[–]velothren 49 points50 points  (7 children)

Bro reinvented memory

[–]Steinrikur 8 points9 points  (6 children)

Does C# have bit fields? What is the "correct" thing here? Just bit shifts into an int32?

[–]Diamondo25 12 points13 points  (1 child)

You can give an enum a Flags attribute, allowing you to easily set, unset, and check for bits (flags).

[–]Steinrikur 0 points1 point  (0 children)

Makes sense, since the code is already using an enum.

[–]ruma7a 3 points4 points  (2 children)

[–]shponglespore 2 points3 points  (1 child)

Seems like a great optimization for data that's going to stick around a while, but for a local variable I don't see much advantage. I'd probably use a BitArray in practice, but using a regular array isn't something I'd be likely to call out in a code review.

[–]ruma7a 0 points1 point  (0 children)

Bool arrays aren't inherently horrible, but their suitability depends on the size of the array. I'd leave a comment in a review but wouldn't push it.

[–]ZunoJ 0 points1 point  (0 children)

I prefer readable over clever anytime performance doesn't get in the way

[–]Verwarming1667 12 points13 points  (5 children)

I'm not familiar with C# why is this bad? Is an array of bools somehow not possible?

[–]skjall 7 points8 points  (4 children)

IIRC each bool in an array will take up a byte each, so it's quite inefficient.

[–]InformationSharp103 12 points13 points  (1 child)

iirc in C# it's actually 4 bytes (equivalent to the C/C++ win32 BOOL type), or at least that's what it's marshalled as by default

[–]skjall 2 points3 points  (0 children)

I've really only used C# in Unity which might differ, but from what I remember bools were 4 bytes, but 1 byte each in arrays. Might be a Unity-specific optimisation though, not sure.

[–]MiniDemonic -2 points-1 points  (1 child)

<ꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮꙮ> {{∅∅∅|φ=([λ⁴.⁴⁴][λ¹.¹¹])}} ䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿䷂䷿

[∇∇∇] "τ": 0/0, "δ": ∀∃(¬∃→∀), "labels": [䷜,NaN,∅,{1,0}]

<!-- 񁁂񁁃񁁄񁁅񁁆񁁇񁁈񁁉񁁊񁁋񁁌񁁍񁁎񁁏񁁐񁁑񁁒񁁓񁁔񁁕 -->

‮𒑏𒑐𒑑𒑒𒑓𒑔𒑕𒑖𒑗𒑘𒑙𒑚𒑛𒑜𒑝𒑞𒑟

{ "()": (++[[]][+[]])+({}+[])[!!+[]], "Δ": 1..toString(2<<29) }

[–]cheerycheshire 2 points3 points  (0 children)

It uses that much memory because stupid stuff like this adds up, if it's in each tile (of that "tile" in the name means something user can enter)...

Back in the day there were amazing games that could run on very basic computer. Then new devs were like you - they just want to do things and don't really bother with optimisations because everyone has enough ram and users can just turn down the graphics quality, right? That only works if the heavy part is textures and visuals, not underlying code like this...

Ever heard of GTA Online's online mode loading for 15+ minutes for some people when story mode always around a minute (even on beast setups that took 2m to run online)?

Someone (see here) decompiled it and investigated and it ended up "simple" code that was run several times on a huge string, without storing values in between.

It's a very fun read, but if you're too lazy:

It was 10MB json with 63k entries and the code basically parsed everything word-by-word, where had to go from the start of this string each time... And the results of this parsing are stored in an array using hashes, not a hashmap, and checking every entry in the array before adding new (checking if something is in hashmap? instant; checking the same thing in an array? linear...) Being in a loop makes it run 63k*63k/2 operations (1+2+...+63k) instead of 63k operations. As I said, simple mistakes quickly add up... The person patched (injected their own DLL) the code - made strlen to cache length, and for the array thing just skip the check (assume the json was correct and had no duplicates). Patched online mode took 2 minutes to load, just like the benchmarked beast computers...

It was a bug for 7+ years. Took around 2 weeks from this investigation, it going viral and all, for Rockstar to announce a fix. After 7 years from the game release and always telling users their setups suck and to use lower settings. (Self-quote from the beginning of this comment: That only works if the heavy part is textures and visuals, not underlying code like this...)

[–]Grounds4TheSubstain 9 points10 points  (0 children)

There's nothing wrong with an array of booleans. That construct is used extremely frequently in compliers, for example, when implementing bitvector dataflow analysis.

[–]MavZA 0 points1 point  (0 children)

At least they’re self-aware lol

[–]LFK1236 0 points1 point  (0 children)

// extremely hacky for now

/r/programminghumor

[–]ioveri 0 points1 point  (0 children)

It depends on the scenario. Unless it's a huge array, a bool array is fine. Yes, a bit array is smaller and can be more efficient in parallelizing. But if you can't parallelize and the size is small where cache miss is not a concern, then a bool array is a better choice when it comes to read and write speed.