standard pagina oficial implementations iec estándar compilers c++ string winapi stl c++03

pagina - mingw c++ 17



¿Es razonable usar std:: basic_string<t> como un buffer contiguo cuando se dirige a C++ 03? (5)

Sé que en C ++ 03, técnicamente, la plantilla std::basic_string no requiere tener memoria contigua. Sin embargo, tengo curiosidad de cuántas implementaciones existen para los compiladores modernos que realmente aprovechan esta libertad. Por ejemplo, si uno quiere usar basic_string para recibir los resultados de alguna API de C (como el ejemplo a continuación), parece tonto asignar un vector solo para convertirlo en una cadena inmediatamente.

Ejemplo:

DWORD valueLength = 0; DWORD type; LONG errorCheck = RegQueryValueExW( hWin32, value.c_str(), NULL, &type, NULL, &valueLength); if (errorCheck != ERROR_SUCCESS) WindowsApiException::Throw(errorCheck); else if (valueLength == 0) return std::wstring(); std::wstring buffer; do { buffer.resize(valueLength/sizeof(wchar_t)); errorCheck = RegQueryValueExW( hWin32, value.c_str(), NULL, &type, &buffer[0], &valueLength); } while (errorCheck == ERROR_MORE_DATA); if (errorCheck != ERROR_SUCCESS) WindowsApiException::Throw(errorCheck); return buffer;

Sé que un código como este podría reducir ligeramente la portabilidad porque implica que std::wstring es contigua, pero me pregunto qué tan poco portable es el código. Dicho de otra manera, ¿cómo pueden los compiladores aprovechar la libertad que tiene la memoria no contigua?

EDITAR: Actualicé esta pregunta para mencionar C ++ 03. Los lectores deben tener en cuenta que al apuntar a C ++ 11, el estándar ahora requiere que basic_string sea ​​contigua, por lo que la pregunta anterior no es un problema al apuntar a ese estándar.


Considero bastante seguro suponer que std :: string asigna su almacenamiento de forma contigua.

En este momento, todas las implementaciones conocidas de std::string asignan espacio contiguamente.

Además, el borrador actual de C ++ 0x ( N3000 ) [Editar: Advertencia, enlace directo a PDF grande] requiere que el espacio se asigne contiguamente (§21.4.1 / 5):

Los objetos tipo char en un objeto basic_string se deben almacenar contiguamente. Es decir, para cualquier objeto basic_string s, la identidad & * (s.begin () + n) == & * s.begin () + n se mantendrá para todos los valores de n tales que 0 <= n <s.size ().

Como tal, las posibilidades de una implementación actual o futura de std::string usando almacenamiento no contiguo son esencialmente nulas.


El resultado no está definido y no lo haría. El costo de leer en un vector y luego convertirlo en una cadena es trivial en los montones modernos de C ++. VS el riesgo de que tu código fallezca en Windows 9

también, ¿no necesita un const_cast on & buffer [0]?


Hace un tiempo, surgió la pregunta de si era posible escribir en el almacenamiento de una std::string como si fuera una matriz de caracteres, y dependía de si el contenido de una std::string era contiguo:

Mi respuesta indicó que según un par de fuentes bien conocidas (Herb Sutter y Matt Austern) el estándar actual de C ++ requiere que std::string almacene sus datos contiguos bajo ciertas condiciones (una vez que llame a str[0] asumiendo que str es un std::string ) y ese hecho prácticamente obliga a la mano de cualquier implementación.

Básicamente, si combinas las promesas hechas por string::data() y string::operator[]() concluyes que &str[0] necesita devolver un buffer contiguo. Por lo tanto, Austern sugiere que el comité simplemente lo haga explícito, y aparentemente eso es lo que sucederá en el estándar 0x (¿o lo están llamando el estándar 1x ahora?).

Así que, hablando en sentido estricto, una implementación no tiene que implementar std::string utilizando almacenamiento contiguo, pero tiene que hacerlo prácticamente a pedido. Y su código de ejemplo hace precisamente eso al pasar &buffer[0] .

Campo de golf:


Por supuesto, asignar un vector aquí es tonto. Usar std :: wstring aquí tampoco es sabio. Es mejor usar una matriz de caracteres para llamar a los winapi. construir un wstring al devolver el valor.


Editar: desea llamar a &buffer[0] , no buffer.data() , porque [] devuelve una referencia no const y notifica al objeto que su contenido puede cambiar inesperadamente.

Sería más limpio hacer buffer.data() , pero debería preocuparse menos por la memoria contigua que por la memoria compartida entre estructuras. string implementaciones de string pueden y deben ser contadas cuando se modifica un objeto. string::data requiere específicamente que el programa no modifique el búfer interno devuelto.

MUY altas posibilidades de que alguna implementación creará un buffer para todas las cadenas sin inicializar además de tener una longitud establecida en 10 o lo que sea.

Use un vector o incluso una matriz con new[] / delete[] . Si realmente no puede copiar el búfer, inicialice legalmente la cadena a algo único antes de cambiarlo.