Bsico de passagem de parmetros em C++

May 31, 2010

[Warning: This post is a backup recovery from my previous Wordpress blog. All content was automatically converted accessing a MySQL database using a Python script (details). Mostly are in Portuguese but if you are interest I can translate to English. If you found any problem dont’t hesitate to contact me in comments.]

para no acontecer certos erros que vi por a...

Em C++ h trs maneiras de passar um parmetro para uma funo, as tradicionais herdadas da linguagem C: valor e ponteiro; alm da novidade: a passagem por referncia. Para ilustrar veja o seguinte exemplo, passar uma estrutura de dados “grande” (neste caso aproximadamente 10 kilobytes) para uma funo:

#include<iostream> #include <string.h>

using namespace std;

struct Big { char text[10000]; int id; };

void f1( Big v ) { cout << v.text << endl; cout << “Ox” << hex << v.id << endl; }

void f2( const Big *v ) { cout << v->text << endl; cout << “Ox” << hex << v->id << endl; }

void f3( const Big &v ) { cout << v.text << endl; cout << “Ox” << hex << v.id << endl; }

int main(int /argc/, char * /argv/[]) {

Big *b0 = new Big; Big b1; Big &b2 = b1;

strcpy(b0->text,“asdfg asdfg asdf asdf asdf asdf”); strcpy(b1.text,“azsxd azsxd azsxd azsxd azsxd azsxd”);

b0->id = 0xbc; b1.id = 0xde;

f2( b0 ); /* pointer */ f1( b1 ); /* value */ f3( b2 ); /* reference */ }

Veja o cdigo assembly gerado pelo compilador (g++) para cada um dos trs casos:

1) Ponteiro

mov    -0xc(%ebp),%eax
mov    %eax,(%esp)
call   0x8048885

2) Valor

movl   $0x0,-0x2728(%ebp)
lea    -0x2720(%ebp),%eax
mov    %eax,-0x272c(%ebp)
jmp    0x8048a36
mov    -0x272c(%ebp),%ecx
mov    -0x2728(%ebp),%edx
movzbl (%ecx,%edx,1),%eax
mov    -0x2728(%ebp),%edx
mov    %al,(%esp,%edx,1)
addl   $0x1,-0x2728(%ebp)
cmpl   $0x2714,-0x2728(%ebp)
jb     0x8048a16
call   0x80488fe

3) Referncia

mov    -0x8(%ebp),%eax
mov    %eax,(%esp)
call   0x804880c

Talvez seja importante:

  • Se voc prefere a sintaxe da intel? Mude no GDB: set disassembly-flavor intel
  • No precisa ser muito esperto para ver que a passagem por valor a pior de todas, veja quanto cdigo assembly foi gerado [#fail]
  • A passagem por referncia inclusive mais eficiente pois aloca no %ebp (base pointer) [8 bytes ao invs de 12 bytes do ponteiro].
  • A passagem por referncia prov a eficincia da passagem por ponteiros com a clareza da passagem por valor.