Here's clojure's definition of vector
:
(defn vector
"Creates a new vector containing the args."
{:added "1.0"
:static true}
([] [])
([a] [a])
([a b] [a b])
([a b c] [a b c])
([a b c d] [a b c d])
([a b c d & args]
(. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d args))))))))
Why are there so many cases? Or, if there are so many, why aren't there more?
My guess is that it's striking a balance between implementation efficiency and probability, but I don't quite see how this would be more efficient.
“No” C++ is a statically-typed language. A vector will hold an object of a single type, and only a single type.
A vector is implemented as an array which is free to add elements even beyond its predefined size. Basically, this array is controlled by the vector class and as soon as it goes out of bounds, the copy constructor copies it to another array of a bigger size. This bigger array is later used as our main internal array.
std::vector does not cause memory leaks, careless programmers do. You should also include an example that actually exhibits the behavior you are experiencing, including calls to the CRT debug API. There's a good possibility that you're incorrectly interpreting the leaks based on when they are reported.
Arrays are slightly more compact: the size is implicit. Arrays are non-resizable; sometimes this is desirable. Arrays don't require parsing extra STL headers (compile time). It can be easier to interact with straight-C code with an array (e.g. if C is allocating and C++ is using).
4 seems to strike a balance of efficiency between when there are lots of arguments and when there are not many arguments.
As an example:
(defn vector-few
([] [])
([ & args ] (. clojure.lang.LazilyPersistentVector (create args))))
(defn vector-many
([] [])
([a] [a])
([a b] [a b])
([a b c] [a b c])
([a b c d] [a b c d])
([a b c d e] [a b c d e])
([a b c d e f] [a b c d e f])
([a b c d e f & args] (. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d (cons e (cons f args))))))))))
Running a test with 4 elements:
=> (time (dotimes [x 1000000] (vector 1 2 3 4)))
"Elapsed time: 12.082104 msecs"
=> (time (dotimes [x 1000000] (vector-few 1 2 3 4)))
"Elapsed time: 443.056339 msecs"
=> (time (dotimes [x 1000000] (vector-many 1 2 3 4)))
"Elapsed time: 11.812106 msecs"
And then with 5:
=> (time (dotimes [x 1000000] (vector 1 2 3 4 5)))
"Elapsed time: 467.904979 msecs"
=> (time (dotimes [x 1000000] (vector-few 1 2 3 4 5)))
"Elapsed time: 537.080198 msecs"
=> (time (dotimes [x 1000000] (vector-many 1 2 3 4 5)))
"Elapsed time: 10.30695 msecs"
And with 8 (so all of the functions are using the var-args case):
=> (time (dotimes [x 1000000] (vector 1 2 3 4 5 6 7 8)))
"Elapsed time: 832.803266 msecs"
=> (time (dotimes [x 1000000] (vector-few 1 2 3 4 5 6 7 8)))
"Elapsed time: 689.526288 msecs"
=> (time (dotimes [x 1000000] (vector-many 1 2 3 4 5 6 7 8)))
"Elapsed time: 905.95839 msecs"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With