Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Let's take a simple example in C:</p> <pre><code>struct X { /* a lot of data */ }; struct X func1(/*args*/) { struct X result; /* fill in result */ return result; } int func2(/*args*/, struct X *result) { if (result == NULL) return -1; /* fill in *result */ return 0; } /* in the code */ struct X x; x = func1(/* args */); func2(/* args */, &amp;x); </code></pre> <p><code>func1</code>, fills in necessary data on its own stack frame, then the line <code>x = func1(...)</code> copies it over to <code>x</code>. <code>func2</code> gets the pointer to <code>x</code> as its argument and fills it in.</p> <p>As you can see here, there are two disadvantages using <code>func1</code>:</p> <ol> <li>You can't report error, unless setting <code>x</code> to an invalid state (which may not exist for all structs, e.g. a matrix)</li> <li>You have to copy possibly large amount of data.</li> </ol> <p>In some cases, error may not be possible at all, so point 1 may not necessarily hold. Point 2 however is a performance killer if your struct is large.</p> <p>Now imagine the same thing in C++, except <code>struct X</code> is now <code>class X</code>, with a copy constructor and a bunch of <code>std::string</code> and <code>std::list</code> etc inside it. The performance gain of using <code>func2</code> becomes even more because copying an object of class <code>X</code> now requires calling multiple copy constructors, deep copying everything, and then destructing the local object inside <code>func1</code>. (With C++11 this would be less bad (as bad as in C) because the object can be moved).</p> <p>The only reason one would want to use <code>func1</code> is for readability and ease of writing. For example, compare this:</p> <pre><code>string fix(const string &amp;s); void print(const string &amp;s); string str; print(fix(str)); </code></pre> <p>vs this:</p> <pre><code>void fix(const string &amp;s, string &amp;res); void print(const string &amp;s); string str; string fixed; fix(str, fixed); print(fixed); </code></pre> <p>The first one is clearly more understandable, while the second one is more efficient. Note that in a language like C, the equivalent of the first code may cause a memory leak, so it's not even possible.</p> <p>So the question comes down to which of these two are you more concerned with. If you talk with a Java guy, they probably tell you "the performance difference is so small you won't even notice it". If you talk with a C guy they will probably tell you "the performance difference may be small on <em>some</em> architectures, but that doesn't mean you can go around doing unnecessary stuff".</p> <p>In the post you mentioned, the programmer is trying to improve performance of the library. The functionality he is improving is "filling in a buffer". This cries for passing the buffer as argument:</p> <ul> <li>You don't need to copy the contents of the buffer</li> <li>You can provide your own buffer, whether it is statically or dynamically allocated. <ul> <li>The function doesn't need to allocate memory each time</li> <li>You can reuse the buffer without having to reallocate memory</li> <li>If statically allocated, you don't need to free the buffer</li> </ul></li> <li>You can partially fill in a larger buffer</li> </ul>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload