Recomendaciones generales
Lo siguiente son recomendaciones, no requisitos.
Si estás editando código, tiene sentido seguir el formato del código existente.
El estilo de código es necesario para mantener la coherencia. La coherencia facilita la lectura del código y también hace más fácil buscar en él.
Muchas de las reglas no tienen una razón lógica; vienen dictadas por prácticas establecidas.
1. La mayor parte del formateo se realiza automáticamente con clang-format.
2. La sangría es de 4 espacios. Configure su entorno de desarrollo para que una tabulación agregue cuatro espacios.
3. Las llaves de apertura y cierre deben estar en una línea aparte.
inline void readBoolText(bool & x, ReadBuffer & buf)
{
char tmp = '0';
readChar(tmp, buf);
x = tmp != '0';
}
4. Si el cuerpo completo de la función es un único statement, puede escribirse en una sola línea. Añada espacios alrededor de las 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 pongas espacios alrededor de los paréntesis.
void reinsert(const Value & x)
memcpy(&buf[place_value], &x, sizeof(x));
6. En las expresiones if, for, while y otras similares, se inserta un espacio antes del paréntesis de apertura (a diferencia de las llamadas a funciones).
for (size_t i = 0; i < rows; i += storage.index_granularity)
7. Añade espacios alrededor de los operadores binarios (+, -, *, /, %, …) y el operador ternario ?:.
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 salto de línea, coloque el operador en una nueva línea y aumente la sangría delante de él.
if (elapsed_ns)
message << " ("
<< rows_read_on_server * 1000000000 / elapsed_ns << " rows/s., "
<< bytes_read_on_server * 1000.0 / elapsed_ns << " MB/s.) ";
9. Si lo desea, puede usar espacios para alinear el contenido dentro de una línea.
dst.ClickLogID = click.LogID;
dst.ClickEventID = click.EventID;
dst.ClickGoodEvent = click.GoodEvent;
10. No uses espacios alrededor de los operadores ., ->.
Si es necesario, el operador puede pasarse a la línea siguiente. En ese caso, la sangría delante de él aumenta.
11. No uses un espacio para separar los operadores unarios (--, ++, *, &, …) del argumento.
12. Coloca un espacio después de una coma, pero no antes. La misma regla se aplica para un punto y coma dentro de una expresión for.
13. No utilice espacios para separar el operador [].
14. En una expresión template <...>, utilice un espacio entre template y <; sin espacios después de < ni antes de >.
template <typename TKey, typename TValue>
struct AggregatedStatElement
{}
15. En clases y estructuras, escriba public, private y protected al mismo nivel que class/struct, y aplique sangría al resto del código.
template <typename T>
class MultiVersion
{
public:
/// Versión del objeto para su uso. shared_ptr gestiona el ciclo de vida de la versión.
using Version = std::shared_ptr<const T>;
...
}
16. Si el mismo namespace se utiliza en todo el archivo y no hay nada más significativo, no es necesaria una sangría dentro de namespace.
17. Si el bloque de un if, for, while u otra expresión consta de una sola statement, las llaves son opcionales. En su lugar, coloque la statement en una línea aparte. Esta regla también aplica para if, for, while anidados, …
Pero si la sentencia interna contiene llaves o else, el bloque externo debe escribirse entre llaves.
/// Finalizar escritura.
for (auto & stream : streams)
stream.second->finalize();
18. No debe haber espacios al final de las líneas.
19. Los archivos fuente están codificados en UTF-8.
20. Los caracteres no ASCII pueden usarse en literales de cadena.
<< ", " << (timer.elapsed() / chunks_stats.hits) << " μsec/hit.";
21. No escriba varias expresiones en una sola línea.
22. Agrupe las secciones de código dentro de las funciones y sepárelas con no más de una línea en blanco.
23. Separe las funciones, las clases, etc., con una o dos líneas en blanco.
24. A const (relacionado con un valor) debe escribirse antes del nombre del tipo.
//correcto
const char * pos
const std::string & s
//incorrecto
char const * pos
25. Al declarar un puntero o una referencia, los símbolos * y & deben ir separados por espacios a ambos lados.
//correcto
const char * pos
//incorrecto
const char* pos
const char *pos
26. Al usar tipos de plantilla, asígnales un alias con la palabra clave using (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 puede declararse localmente, por ejemplo, dentro de una función.
//correcto
using FileStreams = std::map<std::string, std::shared_ptr<Stream>>;
FileStreams streams;
//incorrecto
std::map<std::string, std::shared_ptr<Stream>> streams;
27. No declare varias variables de distintos tipos en una misma sentencia.
28. No utilice conversiones de tipo al estilo de C.
//incorrecto
std::cerr << (int)c <<; std::endl;
//correcto
std::cerr << static_cast<int>(c) << std::endl;
29. En clases y structs, agrupa por separado los miembros y las funciones dentro de cada nivel de visibilidad.
30. En clases y structs pequeños, no es necesario separar la declaración del método de su implementación.
Lo mismo se aplica a los métodos pequeños de cualquier clase o struct.
En las clases y structs de plantilla, no separes las declaraciones de los métodos de su implementación (porque, de lo contrario, deben definirse en la misma unidad de traducción).
31. Puedes ajustar las líneas a 140 caracteres, en lugar de 80.
32. Usa siempre los operadores de incremento/decremento con prefijo si no se requiere el posfijo.
for (Names::const_iterator it = column_names.begin(); it != column_names.end(); ++it)
1. Asegúrate de añadir comentarios en 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 de que está mal diseñado.
/** 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. Coloca los comentarios antes del código que describen. En casos excepcionales, los comentarios pueden ir después del código, en la misma línea.
/** Analiza y ejecuta la consulta.
*/
void executeQuery(
ReadBuffer & istr, /// De dónde leer la consulta (y los datos para INSERT, si corresponde)
WriteBuffer & ostr, /// Dónde escribir el resultado
Context & context, /// BD, tablas, tipos de datos, motores, funciones, funciones de agregación...
BlockInputStreamPtr & query_plan, /// Aquí se puede escribir la descripción de cómo se ejecutó la consulta
QueryProcessingStage::Enum stage = QueryProcessingStage::Complete /// Hasta qué etapa procesar la consulta SELECT
)
4. Los comentarios deben escribirse únicamente en inglés.
5. Si está escribiendo una biblioteca, incluya comentarios detallados que la expliquen en el archivo de cabecera principal.
6. No añada comentarios que no aporten 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 está tomado del recurso http://home.tamk.fi/~jaalto/course/coding-style/doc/unmaintainable-code/.
7. No escriba comentarios inútiles (autor, fecha de creación…) al principio de cada archivo.
8. Los comentarios de una sola línea empiezan con tres barras: ///, y los comentarios multilínea empiezan con /**. Estos comentarios se consideran “documentación”.
Nota: Puede usar Doxygen para generar documentación a partir de estos comentarios. Pero, por lo general, no se usa Doxygen porque resulta más cómodo navegar por el código en el IDE.
9. Los comentarios multilínea no deben tener líneas en blanco al principio ni al final (excepto la línea que cierra un comentario multilínea).
10. Para comentar código, use comentarios normales, no comentarios de “documentación”.
11. Elimine las partes comentadas del código antes de hacer commit.
12. No use lenguaje ofensivo en los comentarios ni en el código.
13. No use mayúsculas. No use puntuación excesiva.
14. No use comentarios como delimitadores.
///******************************************************
15. No abra discusiones en los comentarios.
/// ¿Por qué hiciste esto?
16. No hace falta escribir un comentario al final de un bloque para explicar de qué trata.
1. Utiliza letras minúsculas y guiones bajos en los nombres de variables y miembros de clase.
2. Para los nombres de funciones (métodos), usa camelCase empezando con una letra minúscula.
std::string getName() const override { return "Memory"; }
3. Para los nombres de clases (structs), utilice CamelCase, comenzando con una letra mayúscula. No se usan prefijos distintos de I para las interfaces.
class StorageMemory : public IStorage
4. using se nombran de la misma manera que las clases.
5. Nombres de los argumentos de tipo de las plantillas: en los casos simples, use T; T, U; T1, T2.
En los casos más complejos, siga las reglas para los nombres de clase o añada el prefijo T.
template <typename TKey, typename TValue>
struct AggregatedStatElement
6. Los nombres de los argumentos constantes de plantilla deben seguir las reglas de nomenclatura de variables o, en los casos simples, usar N.
template <bool without_www>
struct ExtractDomain
7. Para las clases abstractas (interfaces), puede añadir el prefijo I.
8. Si una variable se usa solo de forma local, puedes usar un nombre corto.
En todos los demás casos, usa un nombre que describa su propósito.
bool info_successfully_loaded = false;
9. Los nombres de los defines y de las constantes globales se escriben en ALL_CAPS con guiones bajos.
#define MAX_SRC_TABLE_NAMES_TO_STORE 1000
10. Los nombres de los archivos deben seguir el mismo estilo que su contenido.
Si un archivo contiene una sola clase, asígnale el mismo nombre que a la clase (CamelCase).
Si el archivo contiene una sola función, asígnale el mismo nombre que a la función (camelCase).
11. Si el nombre contiene una abreviatura, entonces:
- En los nombres de variables, la abreviatura debe escribirse en minúsculas:
mysql_connection (no mySQL_connection).
- En los nombres de clases y funciones, conserva las letras mayúsculas de la abreviatura:
MySQLConnection (no MySqlConnection).
12. Los argumentos del constructor que se usan únicamente para inicializar los miembros de la clase deben tener el mismo nombre que esos miembros, pero con un guion 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 puede omitirse si el argumento no se usa en el cuerpo del constructor.
13. No hay diferencia entre los nombres de las variables locales y los miembros de la clase (no se requieren prefijos).
14. Para las constantes de un enum, usa CamelCase con inicial mayúscula. ALL_CAPS también es aceptable. Si el enum no es local, usa una enum class.
enum class CompressionMethod
{
QuickLZ = 0,
LZ4 = 1,
};
15. Todos los nombres deben estar en inglés. No se permite la transliteración de palabras en hebreo.
no T_PAAMAYIM_NEKUDOTAYIM
16. Se aceptan abreviaturas si son bien conocidas (cuando puedes encontrar fácilmente su significado en Wikipedia o en un motor de búsqueda).
AST, SQL.
No NVDH (unas letras aleatorias cualquiera)
Se aceptan palabras incompletas si la versión abreviada es de uso común.
También puedes usar una abreviatura si el nombre completo aparece junto a ella en los comentarios.
17. Los nombres de archivo con código fuente de C++ deben tener la extensión .cpp. Los archivos de cabecera deben tener la extensión .h.
1. Gestión de memoria.
La liberación manual de memoria (delete) solo puede usarse en código de librería.
En código de librería, el operador delete solo puede usarse en destructores.
En el código de aplicación, la memoria debe liberarla el objeto que es su propietario.
Ejemplos:
- La forma más sencilla es colocar un objeto en la pila o hacerlo miembro de otra clase.
- Para una gran cantidad de objetos pequeños, use contenedores.
- Para liberar automáticamente una pequeña cantidad de objetos alojados en el heap, use
shared_ptr/unique_ptr.
2. Gestión de recursos.
Use RAII y consulte lo anterior.
3. Manejo de errores.
Use excepciones. En la mayoría de los casos, solo necesita lanzar una excepción y no necesita capturarla (gracias a RAII).
En las aplicaciones offline de procesamiento de datos, a menudo es aceptable no capturar excepciones.
En los servidores que atienden solicitudes de usuarios, normalmente basta con capturar las excepciones en el nivel superior del controlador de conexión.
En las funciones de hilo, debe capturar y conservar todas las excepciones para volver a lanzarlas en el hilo principal después de join.
/// Si aún no se han realizado cálculos, calcular el primer bloque de forma síncrona
if (!started)
{
calculate();
started = true;
}
else /// Si los cálculos ya están en curso, esperar el resultado
pool.wait();
if (exception)
exception->rethrow();
Nunca ocultes las excepciones sin gestionarlas. Nunca te limites a registrar todas las excepciones sin más.
//Incorrecto
catch (...) {}
Si necesitas ignorar algunas excepciones, hazlo solo con las específicas y vuelve a lanzar las demás.
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, compruebe siempre el resultado y lance una excepción en caso de error.
if (0 != close(fd))
throw ErrnoException(ErrorCodes::CANNOT_CLOSE_FILE, "Cannot close file {}", file_name);
Puede usar assert para comprobar una invariante en el código.
4. Tipos de excepciones.
No es necesario usar una jerarquía de excepciones compleja en el código de la aplicación. El texto de la excepción debe ser comprensible para un administrador del sistema.
5. Lanzamiento de excepciones desde los destructores.
No se recomienda, pero está permitido.
Use las siguientes opciones:
- Cree una función (
done() o finalize()) que haga de antemano todo el trabajo que pueda dar lugar a una excepción. Si se llamó a esa función, después no debería haber excepciones en el destructor.
- Las tareas demasiado complejas (como enviar mensajes a través de la red) pueden colocarse en un método independiente 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 de noexcept de forma predeterminada en C++11) para gestionar las excepciones.
6. Bloques de código anónimos.
Puede crear un bloque de código independiente dentro de una sola función para que ciertas variables sean locales, de modo que los destructores se llamen 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. Multihilo.
En programas de procesamiento de datos offline:
- Intente obtener el mejor rendimiento posible en un solo núcleo de CPU. Después, si es necesario, podrá paralelizar el código.
En aplicaciones de servidor:
- Use el pool de hilos para procesar peticiones. Hasta ahora, no hemos tenido ninguna tarea que requiera cambio de contexto en espacio de usuario.
No se usa fork para la paralelización.
8. Sincronización de hilos.
A menudo es posible hacer que distintos hilos usen distintas celdas de memoria (mejor aún: distintas líneas de caché) y no usar ningún mecanismo de sincronización entre hilos (excepto joinAll).
Si se requiere sincronización, en la mayoría de los casos basta con usar mutex con lock_guard.
En otros casos, use primitivas de sincronización del sistema. No use espera activa.
Las operaciones atómicas deben usarse solo en los casos más simples.
No intente implementar estructuras de datos lock-free a menos que sea su principal área de especialización.
9. Punteros frente a referencias.
En la mayoría de los casos, prefiera las referencias.
10. const.
Use referencias constantes, punteros a constantes, const_iterator y métodos const.
Considere const como la opción predeterminada y use variantes sin const solo cuando sea necesario.
Al pasar variables por valor, usar const normalmente no tiene sentido.
11. unsigned.
Use unsigned si es necesario.
12. Tipos numéricos.
Usa los tipos UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32 e Int64, así como size_t, ssize_t y ptrdiff_t.
No uses estos tipos para números: signed/unsigned long, long long, short, signed/unsigned char, char.
13. Paso de argumentos.
Pasa los valores complejos por valor si se van a mover y usa std::move; pásalos por referencia si quieres actualizar el valor en un bucle.
Si una función asume la propiedad de un objeto creado en el heap, haz que el tipo del argumento sea shared_ptr o unique_ptr.
14. Valores de retorno.
En la mayoría de los casos, simplemente usa return. No escribas return std::move(res).
Si la función reserva un objeto en el heap y lo devuelve, usa shared_ptr o unique_ptr.
En casos poco frecuentes (actualizar un valor en un bucle), puede que necesites devolver el valor mediante un argumento. En ese caso, el argumento debe ser una referencia.
using AggregateFunctionPtr = std::shared_ptr<IAggregateFunction>;
/** Permite crear una función de agregación por su nombre.
*/
class AggregateFunctionFactory
{
public:
AggregateFunctionFactory();
AggregateFunctionPtr get(const String & name, const DataTypes & argument_types) const;
15. namespace.
No es necesario usar un namespace separado para el código de la aplicación.
Las bibliotecas pequeñas tampoco lo necesitan.
En bibliotecas medianas o grandes, ponga todo en un namespace.
En el archivo .h de la biblioteca, puede usar namespace detail para ocultar detalles de implementación que el código de la aplicación no necesita.
En un archivo .cpp, puede usar un namespace static o anónimo para ocultar símbolos.
Además, se puede usar un namespace para un enum a fin de evitar que los nombres correspondientes terminen en un namespace externo (aunque es mejor usar un enum class).
16. Inicialización diferida.
Si se requieren argumentos para la inicialización, normalmente no debería escribir un constructor predeterminado.
Si más adelante necesita posponer la inicialización, puede agregar un constructor predeterminado que cree un objeto no válido. O, para una cantidad pequeña de objetos, puede usar shared_ptr/unique_ptr.
Loader(DB::Connection * connection_, const std::string & query, size_t max_block_size_);
/// Para inicialización diferida
Loader() {}
17. Funciones virtuales.
Si la clase no está pensada para uso polimórfico, no es necesario que las funciones sean virtuales. Esto también se aplica al destructor.
18. Codificación.
Use UTF-8 en todas partes. Use std::string y char *. No use std::wstring ni wchar_t.
19. Logging.
Vea los ejemplos en todo el código.
Antes de hacer commit, elimine todo logging irrelevante y de depuración, así como cualquier otro tipo de salida de depuración.
Debe evitarse el logging en bucles, incluso en el nivel Trace.
Los logs deben ser legibles en cualquier nivel de logging.
Por lo general, el logging solo debe usarse en el código de aplicación.
Los mensajes de log deben escribirse en inglés.
Preferiblemente, el log debe ser comprensible para el administrador del sistema.
No use lenguaje vulgar en el log.
Use codificación UTF-8 en el log. En casos excepcionales, puede usar caracteres no ASCII en el log.
20. Entrada/salida.
No use iostreams en bucles internos críticos para el rendimiento de la aplicación (y nunca use stringstream).
Use en su lugar la biblioteca DB/IO.
21. Fecha y hora.
Vea la biblioteca DateLUT.
22. include.
Use siempre #pragma once en lugar de guardas de inclusión.
23. using.
No se usa using namespace. Puede usar using para algo específico. Pero hágalo de forma local dentro de una clase o función.
24. No use trailing return type para las funciones, salvo que sea necesario.
25. Declaración e inicialización de variables.
//forma correcta
std::string s = "Hello";
std::string s{"Hello"};
//forma incorrecta
auto s = std::string{"Hello"};
26. Para las funciones virtuales, escribe virtual en la clase base, pero override en lugar de virtual en las clases derivadas.
Características no utilizadas de C++
1. No se usa la herencia virtual.
2. Construcciones que cuentan con azúcar sintáctico práctico en el C++ moderno, p. ej.
// Forma tradicional sin azúcar sintáctico
template <typename G, typename = std::enable_if_t<std::is_same<G, F>::value, void>> // SFINAE mediante std::enable_if, uso de ::value
std::pair<int, int> func(const E<G> & e) // tipo de retorno especificado explícitamente
{
if (elements.count(e)) // prueba de pertenencia con .count()
{
// ...
}
elements.erase(
std::remove_if(
elements.begin(), elements.end(),
[&](const auto x){
return x == 1;
}),
elements.end()); // patrón remove-erase
return std::make_pair(1, 2); // crear par mediante make_pair()
}
// Con azúcar sintáctico (C++14/17/20)
template <typename G>
requires std::same_v<G, F> // SFINAE mediante concepto de C++20, uso del alias de plantilla de C++14
auto func(const E<G> & e) // tipo de retorno auto (C++14)
{
if (elements.contains(e)) // prueba de pertenencia con .contains de C++20
{
// ...
}
elements.erase_if(
elements,
[&](const auto x){
return x == 1;
}); // std::erase_if de C++20
return {1, 2}; // o: return std::pair(1, 2); // crear par mediante lista de inicialización o inicialización por valor (C++17)
}
1. Escribimos código para una plataforma específica.
Pero, en igualdad de condiciones, se prefiere el código multiplataforma o portable.
2. Lenguaje: C++20 (consulte la lista de funcionalidades disponibles de C++20).
3. Compilador: clang. En el momento de redactar esto (marzo de 2025), el código se compila con clang versión >= 19.
Se utiliza la biblioteca estándar (libc++).
4. SO: Ubuntu Linux, no más antiguo que Precise.
5. El código está escrito para la arquitectura de CPU x86_64.
El conjunto de instrucciones de la CPU es el conjunto mínimo compatible entre nuestros servidores. Actualmente, es SSE 4.2.
6. Use las opciones de compilación -Wall -Wextra -Werror -Weverything con algunas excepciones.
7. Use enlazado estático con todas las bibliotecas, excepto aquellas que sean difíciles de enlazar estáticamente (vea la salida del comando ldd).
8. El código se desarrolla y depura con la configuración de release.
1. KDevelop es un buen IDE.
2. Para depurar, usa gdb, valgrind (memcheck), strace, -fsanitize=... o tcmalloc_minimal_debug.
3. Para el análisis de rendimiento, usa Linux Perf, valgrind (callgrind) o strace -cf.
4. El código fuente está en Git.
5. La compilación usa CMake.
6. Los programas se distribuyen en paquetes deb.
7. Los commits a master no deben romper la compilación.
Aunque solo determinadas revisiones se consideran utilizables.
8. Haz commits tan a menudo como sea posible, incluso si el código solo está parcialmente listo.
Usa ramas para ello.
Si tu código en la rama master aún no compila, exclúyelo de la compilación antes de hacer push. Tendrás que terminarlo o eliminarlo en unos pocos días.
9. Para cambios no triviales, usa ramas y publícalas en el servidor.
10. El código no utilizado se elimina del repositorio.
1. Se usa la biblioteca estándar de C++20 (se permiten extensiones experimentales), así como los frameworks boost y Poco.
2. No se permite usar bibliotecas de paquetes del sistema operativo. Tampoco se permite usar bibliotecas preinstaladas. Todas las bibliotecas deben incluirse como código fuente en el directorio contrib y compilarse con ClickHouse. Consulta Directrices para añadir nuevas bibliotecas de terceros para más detalles.
3. Siempre se da preferencia a las bibliotecas que ya se están utilizando.
Recomendaciones generales
1. Escriba la menor cantidad de código posible.
2. Pruebe primero la solución más sencilla.
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 structs.
5. Si es posible, no escriba constructores de copia, operadores de asignación, destructores (salvo uno virtual, si la clase contiene al menos una función virtual), constructores de movimiento ni operadores de asignación por movimiento. En otras palabras, las funciones generadas por el compilador deben funcionar correctamente. Puede usar default.
6. Se recomienda simplificar el código. Reduzca su tamaño siempre que sea posible.
Recomendaciones adicionales
1. Especificar explícitamente std:: para los tipos de stddef.h
no se recomienda. En otras palabras, recomendamos escribir size_t en lugar de std::size_t, porque es más corto.
Es aceptable añadir std::.
2. Especificar explícitamente std:: para las funciones de la biblioteca estándar de C
no se recomienda. En otras palabras, escriba memcpy en lugar de std::memcpy.
La razón es que existen funciones similares no estándar, como memmem. Sí usamos estas funciones de vez en cuando. Estas funciones no existen en namespace std.
Si escribe std::memcpy en lugar de memcpy en todas partes, memmem sin std:: quedará raro.
No obstante, puede seguir usando std:: si lo prefiere.
3. Usar funciones de C cuando las mismas estén disponibles en la biblioteca estándar de C++.
Esto es aceptable si resulta más eficiente.
Por ejemplo, use memcpy en lugar de std::copy para copiar grandes fragmentos de memoria.
4. Argumentos de función en varias líneas.
Se permite cualquiera de los siguientes estilos de ajuste de línea:
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)
Última modificación el 10 de junio de 2026