Introducción (Introduction)

[SP] Usualmente, punteros son uno de los monstruos mas terroríficos que te puedes encontrar en tu aventura de C/C++. Sin embargo, una vez que aprendes como usarlos, vas a ser capaz de ver uno de los pilares mas poderosos de C/C++. En este articulo, te enseñare brevemente alguno de las características de un puntero: Descripción básica, el puntero void*, la literal nullptr, punteros constantes, referencias y referencias rvalue.Sirve mencionarque la principal ventaja de usar punteros es que podemos referencias el lugar de memoria de un objeto, en vez de pasar el objeto completamente (esto puede ser muy costoso en procesamiento).

[EN] Usually, they’re one of the most frightening monsters you’re gonna encounter in your C/C++ adventure. However, once you learn how to use them, you will be able to see one of the biggest powerful pillar of C/C++. In this article, I’m gonna briefly teach you some features of pointer: Basic description,void* pointers, nullptr literal,const pointers, references, and rvalue references.It’s works noting, the principal advantage of using pointer is that we can refer the address of a specific object, instead of passing the whole object (that could be very expensive in processing resources).

[SP] Punteros son la parte del mecanismo del lenguaje besico para referir a la memoria. Generalmente, ellos nos permiten pasar grandes cantidades de datos con bajo costo. A pesar de esto, si usamos erróneamente los punteros hay un alto riesgo de corrupción de memoria o de punteros apuntando a un lugar no valido.  Por ello, algunas implementaciones son mejores con punteros inteligentes contenedores STL.

[EN] Pointers  are part of the basic language mechanisms for referring memory. Mainly, they allow us to pass potentially large amounts of data with low cost. Despite this, there is high risk of memory corruption if they’re implemented incorrectly. Therefore, some implementations could be better to implement with smart pointers or STL containers instead pointers.

[SP] La principal operación de un puntero es la indirección (operador * de prefijo unarío desferenciador) que permite la referencia del objeto que el puntero esta apuntando. Aparte de la indirección, hay una operación del domicilio & del objeto que nos permite obtener directamente el domicilio de un objeto en especifico. Para ilustrar esta idea, el siguiente snippet enseña como usar las operaciones de indirección y domicilio:

[EN]The pointer’s principal operation is indirection (dereferencing unary prefix operator *) that permits us to referring the object pointed by the pointer. Besides indirection, there is the address-of operator &, which allows us to obtain directly the address of a specific object. To illustrate, there is the next snippet that teach you how to use the indirection and address-of operators:

char c='b';
char* n=&c; //n holds the address of c; & is the address-of operator

cout<<"n: "<<n<<endl; //address of c
cout<<"*n: "<<*n<<endl; //Value of c

void* Puntero (void* Pointer)

[SP] En código de bajo nivel, el puntero void* es usado donde necesitamos apuntar una variable de tipo indefinido. Identifica que un tipo de un puntero puede servir como un argumento de una función, o un puntero a un miembro de una clase, por ello algunas operaciones (deferencia e incremento/decremento) pueden resultar en errores de compilación. Como ultimo punto, void* puede ser explícitamente convertido en otro tipo cuando el caso lo requiera. Como ilustración, aquí mostramos una función que trata de usar las operaciones de incremento y deferencia en un puntero void*, además de que al final explícitamente convertimos un void* a un int*.

[EN] In low-level code, the void* pointer is used where we need to address an unknowing type variable. Notice that, this type of pointer can’t serves as a function argument or a pointer to a class member, hence some operations (dereference and increment/decrement) can result in compile-time errors. Lastly, void* can be explicitly converted to another type when the case demands. For illustration, there is a function that try to use the dereference and increment operator in void* pointer,and in the end we explicitly convert back the void* to a int*:

 

void foo(int* pi){

    void* pv=pi;
    // cout<<*pv<<endl;  void* is not a pointer to object type
    //cout<<pv++<<endl; incrementing void* forbidded
    int* pi2=static_cast<int*>(pv); //Explicit conversion to int* back
    cout<<*pi2<<endl;
}

 Literal nullptr (nullptr Literal)

[SP] Cuando no requerimos un puntero para apuntar un objeto, es recomendable usar la literal nullptr. La razón de esto, es que nullptr hace el código mas inteligible y evita confusión potencial en la implementación de punteros. Antes de la existencia de la literal nullptr, zero (0) y NULL (en C) fueron usados como notación de un puntero invalido, y creando una gran confusión. Finalmente, debemos de mencionar que la literal debe de ser usado únicamente con punteros.

[EN] When we don’t require a pointer to point to an object, we should use the nullptr literal. The reason of this is that nullptr makes code more readable and avoids potential confusion in pointer’s implementation. Before the existence of the nullptr literal, zero(0) and NULL(used in C) were used as a notation to the null pointer, and creating a lot of misunderstanding.Lastly, we have to mention that, this literal ought to be used only with pointers.

Punteros Constantes (Const Pointers)

[Sp] En C++, hay dos tipos de significados cuando hablamos de “constantes”:

  • constexp, evalúa y asegura que una variable sea constante en tiempo de compilación.
  • const, determina la inmutabilidad de una variable en un alcance especifico.

Usando punteros constantes podemos prohibir modificaciones al objeto apuntado que es usado en un argumento de una función. Como ejemplo, el siguiente código muestra 4 maneras de usar punteros constantes:

[EN] In C++, there are two related meanings of “constant”:

  • constexp, evaluate and ensure constness at compile time.
  • const, determine variable immutability in a specific scope.

Using const pointers can be useful when we wanna prohibit any modification of a pointed object that is used as a function argument. For example, the next code shows 4 ways to use const with pointers:

 

//Illustrate the use of constness in pointers
    int a=15;
    const int b=16;
    int c=17;

    int* pi=&a; //pointer

    const int* cOp=&b; //is a pointer to a const int

    const int* const cOcP=&b; //is a const pointer to a const int

    int* const OcP=&a; //is a const pointer to a int

    //Okay let's play...
    /*Const pointer means that we're not able 
    to point the pointer to another variable*/

    //cOcP=&a; error: assignment of read-only variable
    cOp=&c; //(Y)

    //Now try to change the const variable

    //*cOcP=17; error: assignment of read-only variable
    *OcP=17; //(Y)

Referencias (References Alias)

[SP] Una referencia es un alias de un objeto, pero en contraste con punteros, no imponen mayor procesamiento de performance, además de que mantienen el mismo sintaxis que el nombre del objeto.

[EN] A reference is an alias for an object, but in contrast with pointers, it doesn’t impose performance overhead, and holds the same syntax as the name of its object.

[SP] El principal uso de referencias es para especificar parámetros efectivos y valores de retorno de funciones. En otras palabras, en nuestro código  puede haber objetos bastantes pesados que pueden ser muy costosos para pasar por valor a una función (en realidad, no estamos pasando el objeto “original”, si no una copia del objeto); entonces un parámetro de referencia es inicializada por el argumento real que es pasado cuando la función es llamada, de esta manera evitando la copia del objeto.

[EN] The principal use of references is to specify effective parameters and return values of functions. In other words, there could be large objects that are expensive to pass by value to a function (actually, we’re not passing the “original” object, but copying it); so a reference parameter is initialized by the actual argument that is passed when the function is called avoiding the copy of itself.

[SP] Una mejor manera que usar parametros de referencia es un parametro de referencia a constante. De esta manera, le estamos diciendo al compilador que se asegugue que no haya ningun intento de cambiar el objeto. Esto, creanme puede salvarte varios dias de estres buscando bugs.

[EN]A better approach than a reference parameter, is a reference to a const parameter. By this way, we’re telling the compiler to make sure that the functions does not attempt to change that object. This, believe me… may save you a few days of stress looking for bugs.

[SP] Como una ilustración, estamos mostrando una declaracion de una funcion (que usa una referencia a constante) que es una parte de un programa Crypto que hemos desarrollado; esta funcion cambia el valor de cada caracter de un string basado en una llave especial:

[EN]As a illustration, We’re showing a elegant function declaration (which use reference to a const) that is part of a Crypto program I had developed; this function change the value of each character of a string based on a special key:

//We ensure no change in the argument value using pointer to const value
QString Crypto::unshift(const QString& str){ //!!
 
  QByteArray ba=str.toLocal8Bit();
 
  for(int i=0;i<ba.size();i++)
    ba[i]=ba[i]-m_usKey;
 
  QString temp(ba);
  return temp;
}

EXTRA Rvalue References

[SP] Con el proposito de motivar tu curiosidad… Determina cual es la funcion swap mas efectiva.

[EN]With the purpose of encourage your curiosity… Determine which swap function is the most effective.

void oldSwap(string a,string b){
    string temp{a};
    a=b;
    b=temp;
}

void swap(string a, string b){
    string temp{static_cast<string&&>(a)};
    a=static_cast<string&&>(b);
    b=static_cast<string&&>(temp);
}

Leave a Reply

Your email address will not be published.