*不*初始化其成员的C++向量? [英] C++ vector that *doesn't* initialize its members?

查看:21
本文介绍了*不*初始化其成员的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.

当我比较 vvector 的构建时间时,我得到了 ~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++向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆