Ответ 1
Для инициализации по умолчанию и значения для структур с предоставленными пользователем конструкторами по умолчанию, которые явно не инициализируют ничего, никакая инициализация не выполняется для неподписанных char членов:
struct uninitialized_char {
unsigned char m;
uninitialized_char() {}
};
// just to be safe
static_assert(1 == sizeof(uninitialized_char), "");
std::vector<uninitialized_char> v(4 * (1<<20));
GetMyDataFromC(reinterpret_cast<unsigned char*>(&v[0]), v.size());
Я думаю, что это даже законно по строгим правилам псевдонимов.
Когда я сравнивал время построения v
против a vector<unsigned char>
, я получил ~ 8 мкс против ~ 12 мс. Более 1000 раз быстрее. Компилятор был clang 3.2 с libС++ и flags: -std=c++11 -Os -fcatch-undefined-behavior -ftrapv -pedantic -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-prototypes
В С++ 11 есть помощник для неинициализированного хранилища, std:: aligned_storage. Хотя для этого требуется размер времени компиляции.
Здесь добавлен пример сравнения общего использования (раз в наносекундах):
ВЕРСИЯ = 1 (vector<unsigned char>
):
clang++ -std=c++14 -stdlib=libc++ main.cpp -DVERSION=1 -ftrapv -Weverything -Wno-c++98-compat -Wno-sign-conversion -Wno-sign-compare -Os && ./a.out
initialization+first use: 16,425,554
array initialization: 12,228,039
first use: 4,197,515
second use: 4,404,043
ВЕРСИЯ = 2 (vector<uninitialized_char>
):
clang++ -std=c++14 -stdlib=libc++ main.cpp -DVERSION=2 -ftrapv -Weverything -Wno-c++98-compat -Wno-sign-conversion -Wno-sign-compare -Os && ./a.out
initialization+first use: 7,523,216
array initialization: 12,782
first use: 7,510,434
second use: 4,155,241
#include <iostream>
#include <chrono>
#include <vector>
struct uninitialized_char {
unsigned char c;
uninitialized_char() {}
};
void foo(unsigned char *c, int size) {
for (int i = 0; i < size; ++i) {
c[i] = '\0';
}
}
int main() {
auto start = std::chrono::steady_clock::now();
#if VERSION==1
using element_type = unsigned char;
#elif VERSION==2
using element_type = uninitialized_char;
#endif
std::vector<element_type> v(4 * (1<<20));
auto end = std::chrono::steady_clock::now();
foo(reinterpret_cast<unsigned char*>(v.data()), v.size());
auto end2 = std::chrono::steady_clock::now();
foo(reinterpret_cast<unsigned char*>(v.data()), v.size());
auto end3 = std::chrono::steady_clock::now();
std::cout.imbue(std::locale(""));
std::cout << "initialization+first use: " << std::chrono::nanoseconds(end2-start).count() << '\n';
std::cout << "array initialization: " << std::chrono::nanoseconds(end-start).count() << '\n';
std::cout << "first use: " << std::chrono::nanoseconds(end2-end).count() << '\n';
std::cout << "second use: " << std::chrono::nanoseconds(end3-end2).count() << '\n';
}
Я использую clang svn-3.6.0 r218006