Add resize_initialized and resize_uninitialized to Vector. These functions serve as replacements for resize, to make sure the caller understands whether elements need to be initialized 'by hand' after the call.

This commit is contained in:
Lukas Tenbrink 2025-05-23 00:20:22 +02:00
parent 6c9765d87e
commit 4cb8a0c77e
24 changed files with 62 additions and 44 deletions

View file

@ -118,7 +118,7 @@ Error PCKPacker::add_file_removal(const String &p_target_path) {
pf.size = 0;
pf.removal = true;
pf.md5.resize_zeroed(16);
pf.md5.resize_initialized(16);
files.push_back(pf);

View file

@ -99,8 +99,26 @@ public:
_FORCE_INLINE_ T get(Size p_index) { return _cowdata.get(p_index); }
_FORCE_INLINE_ const T &get(Size p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
Error resize(Size p_size) { return _cowdata.template resize<!std::is_trivially_constructible_v<T>>(p_size); }
Error resize_zeroed(Size p_size) { return _cowdata.template resize<true>(p_size); }
/// Resize the vector.
/// Elements are initialized (or not) depending on what the default C++ behavior for this type is.
_FORCE_INLINE_ Error resize(Size p_size) {
return _cowdata.template resize<!std::is_trivially_constructible_v<T>>(p_size);
}
/// Resize and set all values to 0 / false / nullptr.
/// This is only available for zero constructible types.
_FORCE_INLINE_ Error resize_initialized(Size p_size) {
return _cowdata.template resize<true>(p_size);
}
/// Resize and set all values to 0 / false / nullptr.
/// This is only available for trivially destructible types (otherwise, trivial resize might be UB).
_FORCE_INLINE_ Error resize_uninitialized(Size p_size) {
// resize() statically asserts that T is compatible, no need to do it ourselves.
return _cowdata.template resize<false>(p_size);
}
_FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); }
// Must take a copy instead of a reference (see GH-31736).
Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }

View file

@ -304,7 +304,7 @@ Error Array::resize(int p_new_size) {
ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
Variant::Type &variant_type = _p->typed.type;
int old_size = _p->array.size();
Error err = _p->array.resize_zeroed(p_new_size);
Error err = _p->array.resize_initialized(p_new_size);
if (!err && variant_type != Variant::NIL && variant_type != Variant::OBJECT) {
for (int i = old_size; i < p_new_size; i++) {
VariantInternal::initialize(&_p->array.write[i], variant_type);

View file

@ -2514,7 +2514,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedByteArray, remove_at, sarray("index"), varray());
bind_method(PackedByteArray, insert, sarray("at_index", "value"), varray());
bind_method(PackedByteArray, fill, sarray("value"), varray());
bind_methodv(PackedByteArray, resize, &PackedByteArray::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedByteArray, resize, &PackedByteArray::resize_initialized, sarray("new_size"), varray());
bind_method(PackedByteArray, clear, sarray(), varray());
bind_method(PackedByteArray, has, sarray("value"), varray());
bind_method(PackedByteArray, reverse, sarray(), varray());
@ -2585,7 +2585,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedInt32Array, remove_at, sarray("index"), varray());
bind_method(PackedInt32Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedInt32Array, fill, sarray("value"), varray());
bind_methodv(PackedInt32Array, resize, &PackedInt32Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedInt32Array, resize, &PackedInt32Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedInt32Array, clear, sarray(), varray());
bind_method(PackedInt32Array, has, sarray("value"), varray());
bind_method(PackedInt32Array, reverse, sarray(), varray());
@ -2609,7 +2609,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedInt64Array, remove_at, sarray("index"), varray());
bind_method(PackedInt64Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedInt64Array, fill, sarray("value"), varray());
bind_methodv(PackedInt64Array, resize, &PackedInt64Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedInt64Array, resize, &PackedInt64Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedInt64Array, clear, sarray(), varray());
bind_method(PackedInt64Array, has, sarray("value"), varray());
bind_method(PackedInt64Array, reverse, sarray(), varray());
@ -2633,7 +2633,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedFloat32Array, remove_at, sarray("index"), varray());
bind_method(PackedFloat32Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedFloat32Array, fill, sarray("value"), varray());
bind_methodv(PackedFloat32Array, resize, &PackedFloat32Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedFloat32Array, resize, &PackedFloat32Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedFloat32Array, clear, sarray(), varray());
bind_method(PackedFloat32Array, has, sarray("value"), varray());
bind_method(PackedFloat32Array, reverse, sarray(), varray());
@ -2657,7 +2657,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedFloat64Array, remove_at, sarray("index"), varray());
bind_method(PackedFloat64Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedFloat64Array, fill, sarray("value"), varray());
bind_methodv(PackedFloat64Array, resize, &PackedFloat64Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedFloat64Array, resize, &PackedFloat64Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedFloat64Array, clear, sarray(), varray());
bind_method(PackedFloat64Array, has, sarray("value"), varray());
bind_method(PackedFloat64Array, reverse, sarray(), varray());
@ -2681,7 +2681,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedStringArray, remove_at, sarray("index"), varray());
bind_method(PackedStringArray, insert, sarray("at_index", "value"), varray());
bind_method(PackedStringArray, fill, sarray("value"), varray());
bind_methodv(PackedStringArray, resize, &PackedStringArray::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedStringArray, resize, &PackedStringArray::resize_initialized, sarray("new_size"), varray());
bind_method(PackedStringArray, clear, sarray(), varray());
bind_method(PackedStringArray, has, sarray("value"), varray());
bind_method(PackedStringArray, reverse, sarray(), varray());
@ -2705,7 +2705,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedVector2Array, remove_at, sarray("index"), varray());
bind_method(PackedVector2Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedVector2Array, fill, sarray("value"), varray());
bind_methodv(PackedVector2Array, resize, &PackedVector2Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedVector2Array, resize, &PackedVector2Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedVector2Array, clear, sarray(), varray());
bind_method(PackedVector2Array, has, sarray("value"), varray());
bind_method(PackedVector2Array, reverse, sarray(), varray());
@ -2729,7 +2729,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedVector3Array, remove_at, sarray("index"), varray());
bind_method(PackedVector3Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedVector3Array, fill, sarray("value"), varray());
bind_methodv(PackedVector3Array, resize, &PackedVector3Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedVector3Array, resize, &PackedVector3Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedVector3Array, clear, sarray(), varray());
bind_method(PackedVector3Array, has, sarray("value"), varray());
bind_method(PackedVector3Array, reverse, sarray(), varray());
@ -2753,7 +2753,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedColorArray, remove_at, sarray("index"), varray());
bind_method(PackedColorArray, insert, sarray("at_index", "value"), varray());
bind_method(PackedColorArray, fill, sarray("value"), varray());
bind_methodv(PackedColorArray, resize, &PackedColorArray::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedColorArray, resize, &PackedColorArray::resize_initialized, sarray("new_size"), varray());
bind_method(PackedColorArray, clear, sarray(), varray());
bind_method(PackedColorArray, has, sarray("value"), varray());
bind_method(PackedColorArray, reverse, sarray(), varray());
@ -2777,7 +2777,7 @@ static void _register_variant_builtin_methods_array() {
bind_method(PackedVector4Array, remove_at, sarray("index"), varray());
bind_method(PackedVector4Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedVector4Array, fill, sarray("value"), varray());
bind_methodv(PackedVector4Array, resize, &PackedVector4Array::resize_zeroed, sarray("new_size"), varray());
bind_methodv(PackedVector4Array, resize, &PackedVector4Array::resize_initialized, sarray("new_size"), varray());
bind_method(PackedVector4Array, clear, sarray(), varray());
bind_method(PackedVector4Array, has, sarray("value"), varray());
bind_method(PackedVector4Array, reverse, sarray(), varray());

View file

@ -327,10 +327,10 @@ RID AccessibilityDriverAccessKit::accessibility_create_sub_text_edit_elements(co
Vector<float> char_positions;
Vector<float> char_widths;
char_positions.resize_zeroed(t.length());
char_positions.resize_initialized(t.length());
float *positions_ptr = char_positions.ptrw();
char_widths.resize_zeroed(t.length());
char_widths.resize_initialized(t.length());
float *widths_ptr = char_widths.ptrw();
float size_x = 0.0;

View file

@ -227,7 +227,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
if (!(new_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && (new_surface.format & RS::ARRAY_FORMAT_NORMAL) && !(new_surface.format & RS::ARRAY_FORMAT_TANGENT)) {
// Unfortunately, we need to copy the buffer, which is fine as doing a resize triggers a CoW anyway.
Vector<uint8_t> new_vertex_data;
new_vertex_data.resize_zeroed(new_surface.vertex_data.size() + sizeof(uint16_t) * 2);
new_vertex_data.resize_initialized(new_surface.vertex_data.size() + sizeof(uint16_t) * 2);
memcpy(new_vertex_data.ptrw(), new_surface.vertex_data.ptr(), new_surface.vertex_data.size());
GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->vertex_buffer, new_vertex_data.size(), new_vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh vertex buffer");
s->vertex_buffer_size = new_vertex_data.size();

View file

@ -868,10 +868,10 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) {
particles->process_buffer_stride_cache = sizeof(float) * 4 * particles->num_attrib_arrays_cache;
PackedByteArray data;
data.resize_zeroed(particles->process_buffer_stride_cache * total_amount);
data.resize_initialized(particles->process_buffer_stride_cache * total_amount);
PackedByteArray instance_data;
instance_data.resize_zeroed(particles->instance_buffer_size_cache);
instance_data.resize_initialized(particles->instance_buffer_size_cache);
{
glGenVertexArrays(1, &particles->front_vertex_array);

View file

@ -141,7 +141,7 @@ static void merge_constructors(Vector<DocData::MethodDoc> &p_to, const Vector<Do
// the arguments so we make sure they are different.
int64_t arg_count = from.arguments.size();
Vector<bool> arg_used;
arg_used.resize_zeroed(arg_count);
arg_used.resize_initialized(arg_count);
// Also there is no guarantee that argument ordering will match,
// so we have to check one by one so we make sure we have an exact match.
for (int64_t arg_i = 0; arg_i < arg_count; ++arg_i) {

View file

@ -1651,7 +1651,7 @@ Error EditorExportPlatform::_remove_pack_file(void *p_userdata, const String &p_
pd->f->store_8(0);
}
sd.md5.resize_zeroed(16);
sd.md5.resize_initialized(16);
pd->file_ofs.push_back(sd);

View file

@ -3337,13 +3337,13 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
const int *indices_w = indices.ptrw();
Vector<bool> used_indices;
used_indices.resize_zeroed(orig_vertex_num);
used_indices.resize_initialized(orig_vertex_num);
bool *used_w = used_indices.ptrw();
for (int idx_i = 0; idx_i < is; idx_i++) {
ERR_FAIL_INDEX_V(indices_w[idx_i], orig_vertex_num, ERR_INVALID_DATA);
used_w[indices_w[idx_i]] = true;
}
indices_rev_mapping.resize_zeroed(orig_vertex_num);
indices_rev_mapping.resize_initialized(orig_vertex_num);
int *rev_w = indices_rev_mapping.ptrw();
vertex_num = 0;
for (int vert_i = 0; vert_i < orig_vertex_num; vert_i++) {

View file

@ -108,7 +108,7 @@ void OpenXRDpadBindingModifier::_bind_methods() {
}
OpenXRDpadBindingModifier::OpenXRDpadBindingModifier() {
ERR_FAIL_COND(dpad_bindings_data.resize_zeroed(sizeof(XrInteractionProfileDpadBindingEXT)) != OK);
ERR_FAIL_COND(dpad_bindings_data.resize_initialized(sizeof(XrInteractionProfileDpadBindingEXT)) != OK);
dpad_bindings = (XrInteractionProfileDpadBindingEXT *)dpad_bindings_data.ptrw();
dpad_bindings->type = XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT;

View file

@ -1931,7 +1931,7 @@ Ref<Image> DisplayServerMacOS::screen_get_image_rect(const Rect2i &p_rect) const
NSUInteger height = CGImageGetHeight(image);
Vector<uint8_t> img_data;
img_data.resize_zeroed(height * width * 4);
img_data.resize_initialized(height * width * 4);
CGContextRef context = CGBitmapContextCreate(img_data.ptrw(), width, height, 8, 4 * width, color_space, (uint32_t)kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
if (context) {
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);

View file

@ -231,7 +231,7 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
// Terminate string and fill the remaining part of the original string with the '\0'.
Vector<uint8_t> padding_buffer;
padding_buffer.resize_zeroed((int64_t)original_path_size - u8.size());
padding_buffer.resize_initialized((int64_t)original_path_size - u8.size());
file->store_buffer(padding_buffer);
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Failed to write a new PDB path to '%s'.", p_dll_path));

View file

@ -341,7 +341,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (d.has("handle_modes")) {
handle_modes = d["handle_modes"];
} else {
handle_modes.resize_zeroed(times.size());
handle_modes.resize_initialized(times.size());
}
#endif // TOOLS_ENABLED

View file

@ -645,7 +645,7 @@ Array SurfaceTool::commit_to_arrays() {
case Mesh::ARRAY_BONES: {
int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
Vector<int> array;
array.resize_zeroed(varr_len * count);
array.resize_initialized(varr_len * count);
int *w = array.ptrw();
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
@ -668,7 +668,7 @@ Array SurfaceTool::commit_to_arrays() {
Vector<float> array;
int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
array.resize_zeroed(varr_len * count);
array.resize_initialized(varr_len * count);
float *w = array.ptrw();
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {

View file

@ -437,7 +437,7 @@ void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) {
#if defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
Vector<uint8_t> dm;
dm.resize_zeroed(fog_size.x * fog_size.y * fog_size.z * 4);
dm.resize_initialized(fog_size.x * fog_size.y * fog_size.z * 4);
density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
RD::get_singleton()->set_resource_name(density_map, "Fog density map");

View file

@ -189,9 +189,9 @@ void ShaderRD::_initialize_version(Version *p_version) {
p_version->valid = false;
p_version->dirty = false;
p_version->variants.resize_zeroed(variant_defines.size());
p_version->variants.resize_initialized(variant_defines.size());
p_version->variant_data.resize(variant_defines.size());
p_version->group_compilation_tasks.resize_zeroed(group_enabled.size());
p_version->group_compilation_tasks.resize_initialized(group_enabled.size());
}
void ShaderRD::_clear_version(Version *p_version) {
@ -869,7 +869,7 @@ void ShaderRD::initialize(const Vector<VariantDefine> &p_variant_defines, const
}
// Set all to groups to false, then enable those that should be default.
group_enabled.resize_zeroed(max_group_id + 1);
group_enabled.resize_initialized(max_group_id + 1);
bool *enabled_ptr = group_enabled.ptrw();
for (int i = 0; i < p_variant_defines.size(); i++) {
if (p_variant_defines[i].default_enabled) {

View file

@ -383,7 +383,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
if (!(new_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && (new_surface.format & RS::ARRAY_FORMAT_NORMAL) && !(new_surface.format & RS::ARRAY_FORMAT_TANGENT)) {
// Unfortunately, we need to copy the buffer, which is fine as doing a resize triggers a CoW anyway.
Vector<uint8_t> new_vertex_data;
new_vertex_data.resize_zeroed(new_surface.vertex_data.size() + sizeof(uint16_t) * 2);
new_vertex_data.resize_initialized(new_surface.vertex_data.size() + sizeof(uint16_t) * 2);
memcpy(new_vertex_data.ptrw(), new_surface.vertex_data.ptr(), new_surface.vertex_data.size());
s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_vertex_data.size(), new_vertex_data, as_storage_flag);
s->vertex_buffer_size = new_vertex_data.size();
@ -1655,7 +1655,7 @@ void MeshStorage::_multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
}
Vector<uint8_t> newVector;
newVector.resize_zeroed(sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE * mesh->surface_count);
newVector.resize_initialized(sizeof(uint32_t) * INDIRECT_MULTIMESH_COMMAND_STRIDE * mesh->surface_count);
for (uint32_t i = 0; i < mesh->surface_count; i++) {
uint32_t count = mesh_surface_get_vertices_drawn_count(mesh->surfaces[i]);

View file

@ -1379,7 +1379,7 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) {
particles->instance_motion_vectors_enabled = true;
}
data.resize_zeroed(particle_instance_buffer_size);
data.resize_initialized(particle_instance_buffer_size);
particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(particle_instance_buffer_size, data);

View file

@ -3183,7 +3183,7 @@ RID RenderingDevice::vertex_array_create(uint32_t p_vertex_count, VertexFormatID
VertexArray vertex_array;
if (p_offsets.is_empty()) {
vertex_array.offsets.resize_zeroed(p_src_buffers.size());
vertex_array.offsets.resize_initialized(p_src_buffers.size());
} else {
ERR_FAIL_COND_V(p_offsets.size() != p_src_buffers.size(), RID());
vertex_array.offsets = p_offsets;

View file

@ -2339,7 +2339,7 @@ Vector<ShaderLanguage::Scalar> ShaderLanguage::_eval_vector_transform(const Vect
uint32_t ret_size = get_datatype_component_count(p_ret_type);
Vector<Scalar> value;
value.resize_zeroed(ret_size);
value.resize_initialized(ret_size);
Scalar *w = value.ptrw();
switch (p_ret_type) {

View file

@ -63,9 +63,9 @@ void RendererMeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instanc
mmi->_stride = mmi->_vf_size_xform + mmi->_vf_size_color + mmi->_vf_size_data;
int size_in_floats = p_instances * mmi->_stride;
mmi->_data_curr.resize_zeroed(size_in_floats);
mmi->_data_prev.resize_zeroed(size_in_floats);
mmi->_data_interpolated.resize_zeroed(size_in_floats);
mmi->_data_curr.resize_initialized(size_in_floats);
mmi->_data_prev.resize_initialized(size_in_floats);
mmi->_data_interpolated.resize_initialized(size_in_floats);
}
_multimesh_allocate_data(p_multimesh, p_instances, p_transform_format, p_use_colors, p_use_custom_data, p_use_indirect);

View file

@ -207,7 +207,7 @@ TEST_CASE("[FileAccess] Get/Store floating point half precision values") {
// Data should be empty.
PackedByteArray reference;
reference.resize_zeroed(4096);
reference.resize_initialized(4096);
CHECK(reference == full_data);
f->seek(0);
@ -215,7 +215,7 @@ TEST_CASE("[FileAccess] Get/Store floating point half precision values") {
CHECK(partial_data.size() == 4095);
CHECK(!f->eof_reached());
reference.resize_zeroed(4095);
reference.resize_initialized(4095);
CHECK(reference == partial_data);
}
}

View file

@ -133,7 +133,7 @@ TEST_CASE("[PacketPeer][PacketPeerStream] Get packet buffer") {
// First 4 bytes are the length of the string.
CharString cs = godot_rules.ascii();
Vector<uint8_t> buffer = { (uint8_t)(cs.length() + 1), 0, 0, 0 };
buffer.resize_zeroed(4 + cs.length() + 1);
buffer.resize_initialized(4 + cs.length() + 1);
memcpy(buffer.ptrw() + 4, cs.get_data(), cs.length());
spb->set_data_array(buffer);