Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Yes, the compiler will almost certainly do something like a memcpy to copy the struct or class of hundreds of bytes onto the stack if that's what you asked for. If that wasn't the case something like this wouldn't work:</p> <pre><code>std::string s = "A large amount of text"; std::string r = rev(s); std::cout &lt;&lt; s &lt;&lt; " reversed is " &lt;&lt; r &lt;&lt; std::endl; ... std::string rev(std::string s) { std::string::size_type len = s.length(); for(std::string::size_type i = 0; i &lt; len / 2; i++) { swap(s[i], s[len-i]); } return s; } </code></pre> <p>This is why it's nearly always recommended to use <code>const</code> references when possible, as it passes just a pointer to the object.</p> <p>Since the above example got objected to, here's another example:</p> <pre><code>class mystring { char s[200]; size_t len; public: mystring(const char *aS) { strcpy(s, aS); len = strlen(s); } char&amp; operator[](int index) { return s[index]; } size_t length() { return len; } } mystring str("Some long string"); mystring rev = rev_my_str(s); mystring rev_my_str(mystring s) { size_t len = s.length(); for(size_t i = 0; i &lt; len / 2; i++) { swap(s[i], s[len-i]); } return s; } </code></pre> <p>In fact, this will make space for TWO <code>mystring</code> objects on the stack, one for <code>s</code> going into <code>rev_my_str</code>, and one for the return value.</p> <p>Edit:</p> <p>Assembler generated by <code>g++ -O1</code> [1] for the call to <code>rev_my_string</code> as above. The interesting bit is the <code>rep movsq</code> along with the setup of <code>%ecx</code>, <code>%rsi</code> and <code>%rdi</code> (count, source and destination, respectively). $26 is the number of 8 byte units that it will copy. 26 * 8 = 208 bytes. <code>%rsp</code> is the stack pointer. This is almost exactly how a <code>memcpy</code> would look if it was inlined in a simple form [actual <code>memcpy</code> most likely has a whole bunch of extra work to deal with unaligned start/end and using SSE instructions, etc]. </p> <pre><code>movl $26, %ecx movq %rsp, %rdi movq %rbx, %rsi rep movsq leaq 416(%rsp), %rdi call _Z10rev_my_str8mystring </code></pre> <p>And rev_my_string itself looks like this. Note the <code>rep movsq</code> at the bottom of the function. That's where it stores back the resulting string.</p> <pre><code> _Z10rev_my_str8mystring: .LFB990: .cfi_startproc movq %rdi, %rax movq 208(%rsp), %r9 movq %r9, %r10 shrq %r10 je .L5 addq $1, %r10 movl $1, %edx .L6: movl %r9d, %ecx subl %edx, %ecx leaq 7(%rsp), %rsi addq %rdx, %rsi movzbl (%rsi), %edi movslq %ecx, %rcx movzbl 8(%rsp,%rcx), %r8d movb %r8b, (%rsi) movb %dil, 8(%rsp,%rcx) addq $1, %rdx cmpq %r10, %rdx jne .L6 .L5: movl $26, %ecx movq %rax, %rdi leaq 8(%rsp), %rsi rep movsq ret </code></pre> <p>[1] Using higher optimisation than that makes the compiler inline too much of the code (for example the rev_my_string function gets inlined), and it gets very hard to see what goes on. </p>
 

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