* split up select.md * array-join.md basic refactoring * distinct.md basic refactoring * format.md basic refactoring * from.md basic refactoring * group-by.md basic refactoring * having.md basic refactoring * additional index.md refactoring * into-outfile.md basic refactoring * join.md basic refactoring * limit.md basic refactoring * limit-by.md basic refactoring * order-by.md basic refactoring * prewhere.md basic refactoring * adjust operators/index.md links * adjust sample.md links * adjust more links * adjust operatots links * fix some links * adjust aggregate function article titles * basic refactor of remaining select clauses * absolute paths in make_links.sh * run make_links.sh * remove old select.md locations * translate docs/es * translate docs/fr * translate docs/fa * remove old operators.md location * change operators.md links * adjust links in docs/es * adjust links in docs/es * minor texts adjustments * wip * update machine translations to use new links * fix changelog * es build fixes * get rid of some select.md links * temporary adjust ru links * temporary adjust more ru links * improve curly brace handling * adjust ru as well * fa build fix * ru link fixes * zh link fixes * temporary disable part of anchor checks
28 KiB
machine_translated | machine_translated_rev | toc_priority | toc_title |
---|---|---|---|
true | 72537a2d52 |
68 | Cómo escribir código C ++ |
Cómo escribir código C ++
Recomendaciones generales
1. Las siguientes son recomendaciones, no requisitos.
2. Si está editando código, tiene sentido seguir el formato del código existente.
3. El estilo de código es necesario para la coherencia. La consistencia facilita la lectura del código y también facilita la búsqueda del código.
4. Muchas de las reglas no tienen razones lógicas; están dictadas por prácticas establecidas.
Formatear
1. La mayor parte del formato se realizará automáticamente por clang-format
.
2. Las sangrías son 4 espacios. Configure el entorno de desarrollo para que una pestaña agregue cuatro espacios.
3. Abrir y cerrar llaves deben estar en una línea separada.
inline void readBoolText(bool & x, ReadBuffer & buf)
{
char tmp = '0';
readChar(tmp, buf);
x = tmp != '0';
}
4. Si todo el cuerpo de la función es statement
, se puede colocar en una sola línea. Coloque espacios alrededor de llaves (además del espacio al final de la línea).
inline size_t mask() const { return buf_size() - 1; }
inline size_t place(HashValue x) const { return x & mask(); }
5. Para funciones. No coloque espacios alrededor de los corchetes.
void reinsert(const Value & x)
memcpy(&buf[place_value], &x, sizeof(x));
6. En if
, for
, while
y otras expresiones, se inserta un espacio delante del corchete de apertura (a diferencia de las llamadas a funciones).
for (size_t i = 0; i < rows; i += storage.index_granularity)
7. Agregar espacios alrededor de los operadores binarios (+
, -
, *
, /
, %
, …) and the ternary operator ?:
.
UInt16 year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
UInt8 month = (s[5] - '0') * 10 + (s[6] - '0');
UInt8 day = (s[8] - '0') * 10 + (s[9] - '0');
8. Si se introduce un avance de línea, coloque al operador en una nueva línea y aumente la sangría antes de ella.
if (elapsed_ns)
message << " ("
<< rows_read_on_server * 1000000000 / elapsed_ns << " rows/s., "
<< bytes_read_on_server * 1000.0 / elapsed_ns << " MB/s.) ";
9. Puede utilizar espacios para la alineación dentro de una línea, si lo desea.
dst.ClickLogID = click.LogID;
dst.ClickEventID = click.EventID;
dst.ClickGoodEvent = click.GoodEvent;
10. No use espacios alrededor de los operadores .
, ->
.
Si es necesario, el operador se puede envolver a la siguiente línea. En este caso, el desplazamiento frente a él aumenta.
11. No utilice un espacio para separar los operadores unarios (--
, ++
, *
, &
, …) from the argument.
12. Pon un espacio después de una coma, pero no antes. La misma regla se aplica a un punto y coma dentro de un for
expresion.
13. No utilice espacios para separar el []
operador.
14. En un template <...>
expresión, use un espacio entre template
y <
; sin espacios después de <
o antes >
.
template <typename TKey, typename TValue>
struct AggregatedStatElement
{}
15. En clases y estructuras, escribe public
, private
, y protected
en el mismo nivel que class/struct
, y sangrar el resto del código.
template <typename T>
class MultiVersion
{
public:
/// Version of object for usage. shared_ptr manage lifetime of version.
using Version = std::shared_ptr<const T>;
...
}
16. Si el mismo namespace
se usa para todo el archivo, y no hay nada más significativo, no es necesario un desplazamiento dentro namespace
.
17. Si el bloque para un if
, for
, while
, u otra expresión consiste en una sola statement
, las llaves son opcionales. Coloque el statement
en una línea separada, en su lugar. Esta regla también es válida para if
, for
, while
, …
Pero si el interior statement
contiene llaves o else
, el bloque externo debe escribirse entre llaves.
/// Finish write.
for (auto & stream : streams)
stream.second->finalize();
18. No debería haber espacios al final de las líneas.
19. Los archivos de origen están codificados en UTF-8.
20. Los caracteres no ASCII se pueden usar en literales de cadena.
<< ", " << (timer.elapsed() / chunks_stats.hits) << " μsec/hit.";
21. No escriba varias expresiones en una sola línea.
22. Agrupe secciones de código dentro de las funciones y sepárelas con no más de una línea vacía.
23. Separe funciones, clases, etc. con una o dos líneas vacías.
24. A const
(relacionado con un valor) debe escribirse antes del nombre del tipo.
//correct
const char * pos
const std::string & s
//incorrect
char const * pos
25. Al declarar un puntero o referencia, el *
y &
Los símbolos deben estar separados por espacios en ambos lados.
//correct
const char * pos
//incorrect
const char* pos
const char *pos
26. Cuando utilice tipos de plantilla, alias con el using
palabra clave (excepto en los casos más simples).
En otras palabras, los parámetros de la plantilla se especifican solo en using
y no se repiten en el código.
using
se puede declarar localmente, como dentro de una función.
//correct
using FileStreams = std::map<std::string, std::shared_ptr<Stream>>;
FileStreams streams;
//incorrect
std::map<std::string, std::shared_ptr<Stream>> streams;
27. No declare varias variables de diferentes tipos en una instrucción.
//incorrect
int x, *y;
28. No utilice moldes de estilo C.
//incorrect
std::cerr << (int)c <<; std::endl;
//correct
std::cerr << static_cast<int>(c) << std::endl;
29. En clases y estructuras, los miembros del grupo y las funciones por separado dentro de cada ámbito de visibilidad.
30. Para clases y estructuras pequeñas, no es necesario separar la declaración del método de la implementación.
Lo mismo es cierto para los métodos pequeños en cualquier clase o estructura.
Para clases y estructuras con plantillas, no separe las declaraciones de métodos de la implementación (porque de lo contrario deben definirse en la misma unidad de traducción).
31. Puede ajustar líneas en 140 caracteres, en lugar de 80.
32. Utilice siempre los operadores de incremento / decremento de prefijo si no se requiere postfix.
for (Names::const_iterator it = column_names.begin(); it != column_names.end(); ++it)
Comentario
1. Asegúrese de agregar comentarios para todas las partes no triviales del código.
Esto es muy importante. Escribir el comentario puede ayudarte a darte cuenta de que el código no es necesario o que está diseñado incorrectamente.
/** Part of piece of memory, that can be used.
* For example, if internal_buffer is 1MB, and there was only 10 bytes loaded to buffer from file for reading,
* then working_buffer will have size of only 10 bytes
* (working_buffer.end() will point to position right after those 10 bytes available for read).
*/
2. Los comentarios pueden ser tan detallados como sea necesario.
3. Coloque comentarios antes del código que describen. En casos raros, los comentarios pueden aparecer después del código, en la misma línea.
/** Parses and executes the query.
*/
void executeQuery(
ReadBuffer & istr, /// Where to read the query from (and data for INSERT, if applicable)
WriteBuffer & ostr, /// Where to write the result
Context & context, /// DB, tables, data types, engines, functions, aggregate functions...
BlockInputStreamPtr & query_plan, /// Here could be written the description on how query was executed
QueryProcessingStage::Enum stage = QueryProcessingStage::Complete /// Up to which stage process the SELECT query
)
4. Los comentarios deben escribirse en inglés solamente.
5. Si está escribiendo una biblioteca, incluya comentarios detallados que la expliquen en el archivo de encabezado principal.
6. No agregue comentarios que no proporcionen información adicional. En particular, no deje comentarios vacíos como este:
/*
* Procedure Name:
* Original procedure name:
* Author:
* Date of creation:
* Dates of modification:
* Modification authors:
* Original file name:
* Purpose:
* Intent:
* Designation:
* Classes used:
* Constants:
* Local variables:
* Parameters:
* Date of creation:
* Purpose:
*/
El ejemplo se toma prestado del recurso http://home.tamk.fi/~jaalto/course/coding-style/doc/unmaintainable-code/.
7. No escriba comentarios de basura (autor, fecha de creación ..) al principio de cada archivo.
8. Los comentarios de una sola línea comienzan con tres barras: ///
y los comentarios de varias líneas comienzan con /**
. Estos comentarios son considerados “documentation”.
Nota: Puede usar Doxygen para generar documentación a partir de estos comentarios. Pero Doxygen no se usa generalmente porque es más conveniente navegar por el código en el IDE.
9. Los comentarios de varias líneas no deben tener líneas vacías al principio y al final (excepto la línea que cierra un comentario de varias líneas).
10. Para comentar el código, use comentarios básicos, no “documenting” comentario.
11. Elimine las partes comentadas del código antes de confirmar.
12. No use blasfemias en comentarios o código.
13. No use letras mayúsculas. No use puntuación excesiva.
/// WHAT THE FAIL???
14. No use comentarios para hacer delímetros.
///******************************************************
15. No comiencen las discusiones en los comentarios.
/// Why did you do this stuff?
16. No es necesario escribir un comentario al final de un bloque que describa de qué se trataba.
/// for
Nombre
1. Use letras minúsculas con guiones bajos en los nombres de variables y miembros de clase.
size_t max_block_size;
2. Para los nombres de las funciones (métodos), use camelCase comenzando con una letra minúscula.
std::string getName() const override { return "Memory"; }
3. Para los nombres de las clases (estructuras), use CamelCase comenzando con una letra mayúscula. Los prefijos distintos de I no se usan para interfaces.
class StorageMemory : public IStorage
4. using
se nombran de la misma manera que las clases, o con _t
al final.
5. Nombres de argumentos de tipo de plantilla: en casos simples, use T
; T
, U
; T1
, T2
.
Para casos más complejos, siga las reglas para los nombres de clase o agregue el prefijo T
.
template <typename TKey, typename TValue>
struct AggregatedStatElement
6. Nombres de argumentos constantes de plantilla: siga las reglas para los nombres de variables o use N
en casos simples.
template <bool without_www>
struct ExtractDomain
7. Para clases abstractas (interfaces) puede agregar el I
prefijo.
class IBlockInputStream
8. Si usa una variable localmente, puede usar el nombre corto.
En todos los demás casos, use un nombre que describa el significado.
bool info_successfully_loaded = false;
9. Nombres de define
s y las constantes globales usan ALL_CAPS con guiones bajos.
#define MAX_SRC_TABLE_NAMES_TO_STORE 1000
10. Los nombres de archivo deben usar el mismo estilo que su contenido.
Si un archivo contiene una sola clase, nombre el archivo de la misma manera que la clase (CamelCase).
Si el archivo contiene una sola función, nombre el archivo de la misma manera que la función (camelCase).
11. Si el nombre contiene una abreviatura, :
- Para los nombres de variables, la abreviatura debe usar letras minúsculas
mysql_connection
(nimySQL_connection
). - Para los nombres de clases y funciones, mantenga las letras mayúsculas en la abreviatura
MySQLConnection
(niMySqlConnection
).
12. Los argumentos del constructor que se usan solo para inicializar los miembros de la clase deben nombrarse de la misma manera que los miembros de la clase, pero con un guión bajo al final.
FileQueueProcessor(
const std::string & path_,
const std::string & prefix_,
std::shared_ptr<FileHandler> handler_)
: path(path_),
prefix(prefix_),
handler(handler_),
log(&Logger::get("FileQueueProcessor"))
{
}
El sufijo de subrayado se puede omitir si el argumento no se usa en el cuerpo del constructor.
13. No hay diferencia en los nombres de las variables locales y los miembros de la clase (no se requieren prefijos).
timer (not m_timer)
14. Para las constantes en un enum
, usar CamelCase con una letra mayúscula. ALL_CAPS también es aceptable. Si el enum
no es local, utilice un enum class
.
enum class CompressionMethod
{
QuickLZ = 0,
LZ4 = 1,
};
15. Todos los nombres deben estar en inglés. La transliteración de palabras rusas no está permitida.
not Stroka
16. Las abreviaturas son aceptables si son bien conocidas (cuando puede encontrar fácilmente el significado de la abreviatura en Wikipedia o en un motor de búsqueda).
`AST`, `SQL`.
Not `NVDH` (some random letters)
Las palabras incompletas son aceptables si la versión abreviada es de uso común.
También puede usar una abreviatura si el nombre completo se incluye junto a él en los comentarios.
17. Los nombres de archivo con código fuente de C++ deben tener .cpp
ampliación. Los archivos de encabezado deben tener .h
ampliación.
Cómo escribir código
1. Gestión de la memoria.
Desasignación de memoria manual (delete
) solo se puede usar en el código de la biblioteca.
En el código de la biblioteca, el delete
operador sólo se puede utilizar en destructores.
En el código de la aplicación, la memoria debe ser liberada por el objeto que la posee.
Ejemplos:
- La forma más fácil es colocar un objeto en la pila o convertirlo en miembro de otra clase.
- Para una gran cantidad de objetos pequeños, use contenedores.
- Para la desasignación automática de un pequeño número de objetos que residen en el montón, use
shared_ptr/unique_ptr
.
2. Gestión de recursos.
Utilizar RAII
y ver arriba.
3. Manejo de errores.
Utilice excepciones. En la mayoría de los casos, solo necesita lanzar una excepción y no necesita atraparla (debido a RAII
).
En las aplicaciones de procesamiento de datos fuera de línea, a menudo es aceptable no detectar excepciones.
En los servidores que manejan las solicitudes de los usuarios, generalmente es suficiente detectar excepciones en el nivel superior del controlador de conexión.
En las funciones de subproceso, debe capturar y mantener todas las excepciones para volver a lanzarlas en el subproceso principal después join
.
/// If there weren't any calculations yet, calculate the first block synchronously
if (!started)
{
calculate();
started = true;
}
else /// If calculations are already in progress, wait for the result
pool.wait();
if (exception)
exception->rethrow();
Nunca oculte excepciones sin manejo. Nunca simplemente ponga ciegamente todas las excepciones para iniciar sesión.
//Not correct
catch (...) {}
Si necesita ignorar algunas excepciones, hágalo solo para las específicas y vuelva a lanzar el resto.
catch (const DB::Exception & e)
{
if (e.code() == ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION)
return nullptr;
else
throw;
}
Al usar funciones con códigos de respuesta o errno
, siempre verifique el resultado y arroje una excepción en caso de error.
if (0 != close(fd))
throwFromErrno("Cannot close file " + file_name, ErrorCodes::CANNOT_CLOSE_FILE);
Do not use assert
.
4. Tipos de excepción.
No es necesario utilizar una jerarquía de excepciones compleja en el código de la aplicación. El texto de excepción debe ser comprensible para un administrador del sistema.
5. Lanzar excepciones de destructores.
Esto no es recomendable, pero está permitido.
Utilice las siguientes opciones:
- Crear una función (
done()
ofinalize()
) que hará todo el trabajo de antemano que podría conducir a una excepción. Si se llamó a esa función, no debería haber excepciones en el destructor más adelante. - Las tareas que son demasiado complejas (como enviar mensajes a través de la red) se pueden poner en un método separado al que el usuario de la clase tendrá que llamar antes de la destrucción.
- Si hay una excepción en el destructor, es mejor registrarla que ocultarla (si el registrador está disponible).
- En aplicaciones simples, es aceptable confiar en
std::terminate
(para los casos denoexcept
de forma predeterminada en C ++ 11) para manejar excepciones.
6. Bloques de código anónimos.
Puede crear un bloque de código separado dentro de una sola función para hacer que ciertas variables sean locales, de modo que se llame a los destructores al salir del bloque.
Block block = data.in->read();
{
std::lock_guard<std::mutex> lock(mutex);
data.ready = true;
data.block = block;
}
ready_any.set();
7. Multithreading.
En programas de procesamiento de datos fuera de línea:
- Trate de obtener el mejor rendimiento posible en un solo núcleo de CPU. A continuación, puede paralelizar su código si es necesario.
En aplicaciones de servidor:
- Utilice el grupo de subprocesos para procesar solicitudes. En este punto, no hemos tenido ninguna tarea que requiera el cambio de contexto de espacio de usuario.
La horquilla no se usa para la paralelización.
8. Sincronización de hilos.
A menudo es posible hacer que diferentes hilos usen diferentes celdas de memoria (incluso mejor: diferentes líneas de caché) y no usar ninguna sincronización de hilos (excepto joinAll
).
Si se requiere sincronización, en la mayoría de los casos, es suficiente usar mutex bajo lock_guard
.
En otros casos, use primitivas de sincronización del sistema. No utilice la espera ocupada.
Las operaciones atómicas deben usarse solo en los casos más simples.
No intente implementar estructuras de datos sin bloqueo a menos que sea su principal área de especialización.
9. Punteros vs referencias.
En la mayoría de los casos, prefiera referencias.
10. Construir.
Usar referencias constantes, punteros a constantes, const_iterator
, y métodos const.
Considerar const
para ser predeterminado y usar no-const
sólo cuando sea necesario.
Al pasar variables por valor, usando const
por lo general no tiene sentido.
11. sin firmar.
Utilizar unsigned
si es necesario.
12. Tipos numéricos.
Utilice los tipos UInt8
, UInt16
, UInt32
, UInt64
, Int8
, Int16
, Int32
, y Int64
, así como size_t
, ssize_t
, y ptrdiff_t
.
No use estos tipos para números: signed/unsigned long
, long long
, short
, signed/unsigned char
, char
.
13. Pasando argumentos.
Pasar valores complejos por referencia (incluyendo std::string
).
Si una función captura la propiedad de un objeto creado en el montón, cree el tipo de argumento shared_ptr
o unique_ptr
.
14. Valores devueltos.
En la mayoría de los casos, sólo tiene que utilizar return
. No escribir [return std::move(res)]{.strike}
.
Si la función asigna un objeto en el montón y lo devuelve, use shared_ptr
o unique_ptr
.
En casos excepcionales, es posible que deba devolver el valor a través de un argumento. En este caso, el argumento debe ser una referencia.
using AggregateFunctionPtr = std::shared_ptr<IAggregateFunction>;
/** Allows creating an aggregate function by its name.
*/
class AggregateFunctionFactory
{
public:
AggregateFunctionFactory();
AggregateFunctionPtr get(const String & name, const DataTypes & argument_types) const;
15. espacio de nombres.
No hay necesidad de usar un namespace
para el código de aplicación.
Las bibliotecas pequeñas tampoco necesitan esto.
Para bibliotecas medianas a grandes, coloque todo en un namespace
.
En la biblioteca .h
archivo, se puede utilizar namespace detail
para ocultar los detalles de implementación no necesarios para el código de la aplicación.
En un .cpp
archivo, puede usar un static
o espacio de nombres anónimo para ocultar símbolos.
Además, un namespace
puede ser utilizado para un enum
para evitar que los nombres correspondientes caigan en un namespace
(pero es mejor usar un enum class
).
16. Inicialización diferida.
Si se requieren argumentos para la inicialización, normalmente no debe escribir un constructor predeterminado.
Si más adelante tendrá que retrasar la inicialización, puede agregar un constructor predeterminado que creará un objeto no válido. O, para un pequeño número de objetos, puede usar shared_ptr/unique_ptr
.
Loader(DB::Connection * connection_, const std::string & query, size_t max_block_size_);
/// For deferred initialization
Loader() {}
17. Funciones virtuales.
Si la clase no está destinada para uso polimórfico, no necesita hacer que las funciones sean virtuales. Esto también se aplica al destructor.
18. Codificación.
Usa UTF-8 en todas partes. Utilizar std::string
ychar *
. No use std::wstring
ywchar_t
.
19. Tala.
Vea los ejemplos en todas partes del código.
Antes de confirmar, elimine todo el registro de depuración y sin sentido, y cualquier otro tipo de salida de depuración.
Se debe evitar el registro en ciclos, incluso en el nivel Trace.
Los registros deben ser legibles en cualquier nivel de registro.
El registro solo debe usarse en el código de la aplicación, en su mayor parte.
Los mensajes de registro deben estar escritos en inglés.
El registro debe ser preferiblemente comprensible para el administrador del sistema.
No use blasfemias en el registro.
Utilice la codificación UTF-8 en el registro. En casos excepcionales, puede usar caracteres que no sean ASCII en el registro.
20. Entrada-salida.
No utilice iostreams
en ciclos internos que son críticos para el rendimiento de la aplicación (y nunca usan stringstream
).
Utilice el DB/IO
biblioteca en su lugar.
21. Fecha y hora.
Ver el DateLUT
biblioteca.
22. incluir.
Utilice siempre #pragma once
en lugar de incluir guardias.
23. utilizar.
using namespace
no se utiliza. Usted puede utilizar using
con algo específico. Pero hazlo local dentro de una clase o función.
24. No use trailing return type
para funciones a menos que sea necesario.
[auto f() -> void;]{.strike}
25. Declaración e inicialización de variables.
//right way
std::string s = "Hello";
std::string s{"Hello"};
//wrong way
auto s = std::string{"Hello"};
26. Para funciones virtuales, escriba virtual
en la clase base, pero escribe override
en lugar de virtual
en las clases descendientes.
Características no utilizadas de C ++
1. La herencia virtual no se utiliza.
2. Los especificadores de excepción de C ++ 03 no se usan.
Plataforma
1. Escribimos código para una plataforma específica.
Pero en igualdad de condiciones, se prefiere el código multiplataforma o portátil.
2. Idioma: C ++ 17.
3. Compilación: gcc
. En este momento (diciembre de 2017), el código se compila utilizando la versión 7.2. (También se puede compilar usando clang 4
.)
Se utiliza la biblioteca estándar (libstdc++
o libc++
).
**4.**OS: Linux Ubuntu, no más viejo que Precise.
**5.**El código está escrito para la arquitectura de CPU x86_64.
El conjunto de instrucciones de CPU es el conjunto mínimo admitido entre nuestros servidores. Actualmente, es SSE 4.2.
6. Utilizar -Wall -Wextra -Werror
flags de compilación.
7. Use enlaces estáticos con todas las bibliotecas, excepto aquellas a las que son difíciles de conectar estáticamente (consulte la salida de la ldd
comando).
8. El código se desarrolla y se depura con la configuración de la versión.
Herramienta
1. KDevelop es un buen IDE.
2. Para la depuración, use gdb
, valgrind
(memcheck
), strace
, -fsanitize=...
, o tcmalloc_minimal_debug
.
3. Para crear perfiles, use Linux Perf
, valgrind
(callgrind
), o strace -cf
.
4. Las fuentes están en Git.
5. Usos de ensamblaje CMake
.
6. Los programas se lanzan usando deb
paquete.
7. Los compromisos a dominar no deben romper la compilación.
Aunque solo las revisiones seleccionadas se consideran viables.
8. Realice confirmaciones tan a menudo como sea posible, incluso si el código está parcialmente listo.
Use ramas para este propósito.
Si su código en el master
branch todavía no se puede construir, excluirlo de la compilación antes de la push
. Tendrá que terminarlo o eliminarlo dentro de unos días.
9. Para cambios no triviales, use ramas y publíquelas en el servidor.
10. El código no utilizado se elimina del repositorio.
Biblioteca
1. Se utiliza la biblioteca estándar de C ++ 14 (se permiten extensiones experimentales), así como boost
y Poco
marco.
2. Si es necesario, puede usar cualquier biblioteca conocida disponible en el paquete del sistema operativo.
Si ya hay una buena solución disponible, úsela, incluso si eso significa que debe instalar otra biblioteca.
(Pero prepárese para eliminar las bibliotecas incorrectas del código.)
3. Puede instalar una biblioteca que no esté en los paquetes, si los paquetes no tienen lo que necesita o tienen una versión obsoleta o el tipo de compilación incorrecto.
4. Si la biblioteca es pequeña y no tiene su propio sistema de compilación complejo, coloque los archivos contrib
carpeta.
5. Siempre se da preferencia a las bibliotecas que ya están en uso.
Recomendaciones generales
1. Escribe el menor código posible.
2. Pruebe la solución más simple.
3. No escriba código hasta que sepa cómo va a funcionar y cómo funcionará el bucle interno.
4. En los casos más simples, use using
en lugar de clases o estructuras.
5. Si es posible, no escriba constructores de copia, operadores de asignación, destructores (que no sean virtuales, si la clase contiene al menos una función virtual), mueva constructores o mueva operadores de asignación. En otras palabras, las funciones generadas por el compilador deben funcionar correctamente. Usted puede utilizar default
.
6. Se fomenta la simplificación del código. Reduzca el tamaño de su código siempre que sea posible.
Recomendaciones adicionales
1. Especificar explícitamente std::
para tipos de stddef.h
no se recomienda. En otras palabras, recomendamos escribir size_t
en su lugar std::size_t
porque es más corto.
Es aceptable agregar std::
.
2. Especificar explícitamente std::
para funciones de la biblioteca C estándar
no se recomienda. En otras palabras, escribir memcpy
en lugar de std::memcpy
.
La razón es que hay funciones no estándar similares, tales como memmem
. Utilizamos estas funciones en ocasiones. Estas funciones no existen en namespace std
.
Si usted escribe std::memcpy
en lugar de memcpy
en todas partes, entonces memmem
sin std::
se verá extraño.
Sin embargo, todavía puedes usar std::
si lo prefieres.
3. Usar funciones de C cuando las mismas están disponibles en la biblioteca estándar de C ++.
Esto es aceptable si es más eficiente.
Por ejemplo, use memcpy
en lugar de std::copy
para copiar grandes trozos de memoria.
4. Argumentos de función multilínea.
Se permite cualquiera de los siguientes estilos de ajuste:
function(
T1 x1,
T2 x2)
function(
size_t left, size_t right,
const & RangesInDataParts ranges,
size_t limit)
function(size_t left, size_t right,
const & RangesInDataParts ranges,
size_t limit)
function(size_t left, size_t right,
const & RangesInDataParts ranges,
size_t limit)
function(
size_t left,
size_t right,
const & RangesInDataParts ranges,
size_t limit)