You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建含未初始化数组的std::tuple以避免零初始化开销?

解决方案:创建未初始化的std::tuple并保留NRVO

你希望通过std::tuple从函数返回一组值,避免编译器对tuple内的2KB数组进行清零初始化,同时保留具名返回值优化(NRVO),不想用自定义类实现。原代码中编译器会自动填充tuple内存为0,以下是简便优化方案:

原代码

#include <tuple>
#include <cstdint>
#include <cstddef>

const size_t SHA256_DIGEST_LENGTH = 256 * 8;

unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);

struct uuid {
    uint32_t time_low;
    uint16_t time_mid;
    uint16_t time_hi;
    uint8_t bits[8];
};

void make_uuid(uuid *result);

using uuid_pair = std::tuple<uuid, uint8_t[SHA256_DIGEST_LENGTH]>;

uuid_pair make_uuid()
{
    uuid_pair result;
    make_uuid(&std::get<uuid>(result));
    SHA256((uint8_t *)&std::get<uuid>(result), sizeof(uuid), &std::get<1>(result)[0]);
    return result;
}

核心优化方案:用std::array替代C-style数组

std::tuple对C-style数组的默认构造可能触发值初始化(即清零),而std::array作为聚合类型,默认初始化不会自动清零元素。替换后完全保留NRVO,代码改动极小:

修改后的代码

#include <tuple>
#include <cstdint>
#include <cstddef>
#include <array> // 引入std::array头文件

const size_t SHA256_DIGEST_LENGTH = 256 * 8;

unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);

struct uuid {
    uint32_t time_low;
    uint16_t time_mid;
    uint16_t time_hi;
    uint8_t bits[8];
};

void make_uuid(uuid *result);

// 用std::array替代C-style数组
using uuid_pair = std::tuple<uuid, std::array<uint8_t, SHA256_DIGEST_LENGTH>>;

uuid_pair make_uuid()
{
    uuid_pair result; // 默认初始化,元素均未被清零
    make_uuid(&std::get<0>(result));
    // 用data()获取数组首地址,更规范
    SHA256(reinterpret_cast<uint8_t*>(&std::get<0>(result)), sizeof(uuid), std::get<1>(result).data());
    return result; // NRVO依然生效,无额外拷贝
}

原理说明

  1. 避免清零的原因:std::array<T, N>的默认初始化(std::array<T, N> arr;)不会对元素进行值初始化(即清零),仅分配内存;而原代码中的C-style数组作为std::tuple元素时,编译器可能因语言规则或编译选项(如-ftrivial-auto-var-init=zero)触发值初始化,导致内存被清零。
  2. 保留NRVO:函数返回的是具名局部变量result,编译器会直接在调用方的内存空间构造该tuple,完全避免拷贝或移动操作,性能不受影响。

额外提示(C++20专属)

如果必须使用C-style数组且基于C++20标准,可利用std::tuple的聚合类型特性,直接构造未初始化的tuple:

uuid_pair result; // C++20中std::tuple是聚合类型,默认初始化不会触发值初始化

但此方法依赖C++20标准,且部分编译器可能因默认选项仍触发清零,因此std::array的方案兼容性和可靠性更高。

内容的提问来源于stack exchange,提问作者Kirill Frolov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 16:39:56