C++ vector that *doesn#39;t* initialize its members?(*不*初始化其成员的C++向量?)
问题描述
我正在为一段返回大数组的 C 代码制作 C++ 包装器,因此我尝试以 vector
返回数据.
I'm making a C++ wrapper for a piece of C code that returns a large array, and so I've tried to return the data in a vector<unsigned char>
.
现在的问题是,数据的数量级为 兆字节,并且 vector
不必要地初始化它的存储,结果是把我的速度减半.
Now the problem is, the data is on the order of megabytes, and vector
unnecessarily initializes its storage, which essentially turns out to cut down my speed by half.
我如何防止这种情况发生?
How do I prevent this?
或者,如果不可能——是否有其他一些 STL 容器可以避免这种不必要的工作?或者我必须最终制作自己的容器?
Or, if it's not possible -- is there some other STL container that would avoid such needless work? Or must I end up making my own container?
(C++11 之前的)
(Pre-C++11)
我正在传递向量作为我的输出缓冲区.我不会从别处复制数据.
就像这样:
I'm passing the vector as my output buffer. I'm not copying the data from elsewhere.
It's something like:
vector<unsigned char> buf(size); // Why initialize??
GetMyDataFromC(&buf[0], buf.size());
推荐答案
对于具有用户提供的默认构造函数的结构的默认和值初始化,这些默认构造函数不显式初始化任何内容,不会对 unsigned char 成员执行初始化:
For default and value initialization of structs with user-provided default constructors which don't explicitly initialize anything, no initialization is performed on unsigned char members:
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());
我认为在严格的别名规则下这甚至是合法的.
I think this is even legal under the strict aliasing rules.
当我比较 v
和 vector
的构建时间时,我得到了 ~8 µs 和 ~12 ms.快 1000 倍以上.编译器是带有 libc++ 和标志的 clang 3.2: -std=c++11 -Os -fcatch-undefined-behavior -ftrapv -pedantic -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-prototypes
When I compared the construction time for v
vs. a vector<unsigned char>
I got ~8 µs vs ~12 ms. More than 1000x faster. Compiler was clang 3.2 with libc++ and flags: -std=c++11 -Os -fcatch-undefined-behavior -ftrapv -pedantic -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-prototypes
C++11 有一个用于未初始化存储的助手,std::aligned_storage.虽然它需要一个编译时间大小.
C++11 has a helper for uninitialized storage, std::aligned_storage. Though it requires a compile time size.
这是一个附加示例,用于比较总使用量(以纳秒为单位的时间):
Here's an added example, to compare total usage (times in nanoseconds):
VERSION=1 (vector
):
VERSION=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
VERSION=2 (vector
):
VERSION=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] = ' ';
}
}
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() << '
';
std::cout << "array initialization: " << std::chrono::nanoseconds(end-start).count() << '
';
std::cout << "first use: " << std::chrono::nanoseconds(end2-end).count() << '
';
std::cout << "second use: " << std::chrono::nanoseconds(end3-end2).count() << '
';
}
我正在使用 clang svn-3.6.0 r218006
I'm using clang svn-3.6.0 r218006
这篇关于*不*初始化其成员的C++向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:*不*初始化其成员的C++向量?
基础教程推荐
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01