删除元素后如何返回数组?
Posted
技术标签:
【中文标题】删除元素后如何返回数组?【英文标题】:How can I return the array after deleting an element? 【发布时间】:2021-12-11 05:26:11 【问题描述】:下面的函数
int* del_element(int* vector, int dim, int el)
// ...?
正在接收一个动态分配的数组。我可以在里面写什么来删除元素并返回获得的数组?
【问题讨论】:
为什么不使用std::vector
?
你尝试了吗?为什么要标记vector
?使用vector
这将是微不足道的,没有它会不必要地复杂。你能用vector
吗?
只是作为一个练习,你应该自己编写这样的代码,但是这样的练习只有在你已经知道自己在做什么时才有意义。否则只需使用std::vector
及其erase
无关注意:分配和释放内存的成本很高。通常,如果您只是从数组中删除元素,您只需将删除的元素之后的剩余数组元素移回以覆盖已删除的元素,更新一点簿记以跟踪分配中元素的计数并离开仅分配本身。
Andrew.09:您说过“很遗憾,我无法更改该功能” - 但现在,您有了吗?您已经获得了原始问题的答案,因此您不应过于激进地编辑问题,以至于您获得的答案不再有意义。我已恢复您对函数签名的更改。
【参考方案1】:
这不是一个好主意,但它回答了这个问题。在最初的问题中,您有注释“删除其维度”,我将其解释为您想要缩小分配的内存。示例:
#include <algorithm> // std::copy_n
#include <iostream>
int* del_element(int* vector, int dim, int el)
int* rv = nullptr;
if(--dim > 0) // must have at least 1 element
rv = new int[dim]; // allocate new memory
// copy the the elements before `el`:
std::copy_n(vector, el, rv);
// copy the elements after `el`:
std::copy_n(vector + el + 1, dim - el, rv + el);
delete[] vector; // delete the old data
return rv; // return the new data (nullptr if empty)
int main()
int* v = new int[10]0,1,2,3,4,5,6,7,8,9;
v = del_element(v, 10, 5); // erase the sixth element
for(int* it = v, *end = v + 9; it != end; ++it)
std::cout << *it << '\n';
delete[] v;
无需缩小分配的内存,您只需std::move
数据即可擦除所选元素:
int* del_element(int* vector, int dim, int el)
// move the elements after `el` one step to "the left":
std::move(vector + el + 1, vector + dim, vector + el);
return vector;
更好的方法是使用std::vector<int>
:
#include <iostream>
#include <vector>
int main()
std::vector<int> v0,1,2,3,4,5,6,7,8,9;
v.erase(v.begin() + 5); // erase the sixth element
for(int value : v)
std::cout << value << '\n';
【讨论】:
也许可以回答这个问题。据我们所知,int* v = new int[10]0,1,2,3,4,5,6,7,8,9;
实际上是提问者代码中的int v[10] = 0,1,2,3,4,5,6,7,8,9;
,答案是“你不能这样做,D00d。”
@user4581301 "一个动态分配的数组" 表明它实际上是动态分配的。
我会给你那个,希望他们没有malloc
这个傻瓜。
@user4581301 我也想到了这个想法:-)【参考方案2】:
这是一个糟糕的想法(或者可能是一个糟糕的学校练习)。请使用std::vector
,或者在最坏的情况下使用std::array
。
(另外,也许不要将普通数组称为“vector
”,不要将size
称为dim
(可能与维数混淆),不要使用int
are size_t
应该是,尽可能避免使用原始指针等)
该函数应返回 std::unique_ptr<int[]>
以清楚地记录所有权转移。
如果您应该处理原始数组,请使用std::unique_ptr<int[]>
参数。如果您不应该处理原始数组,请使用const int *
参数。
最重要的是,使用valgrind
仔细检查所有内容;它必须无错误地终止。
最后但同样重要的是,如果可能,不要将元素类型限制为int
;你未来的自己会感谢你的。
#include <memory>
template<typename Element>
std::unique_ptr<Element[]> del_element(std::unique_ptr<Element[]> array,
size_t size, size_t idx)
auto result = std::make_unique<Element[]>(size - 1);
for (size_t i = 0; i < idx; ++i) result[i] = array[i];
for (size_t i = idx + 1; i < size; ++i) result[i - 1] = array[i];
return result;
另外,设置打印功能进行调试。
#include <iostream>
template<typename Element>
void print_array(const Element *array, size_t size)
std::cout << '[';
if (size)
std::cout << *array;
for (size_t i = 1; i < size; ++i) std::cout << ", " << array[i];
std::cout << ']' << std::endl;
另外,别忘了测试它。 valgrind
是你的朋友!
int main()
std::unique_ptr<int[]> first = std::make_unique<int[]>(7);
for (size_t i = 0; i < 7; ++i) first[i] = i - 3;
print_array(first.get(), 7);
std::unique_ptr<int[]> second = del_element(std::move(first), 7, 3);
print_array(second.get(), 6);
std::unique_ptr<int[]> third = del_element(std::move(second), 6, 0);
print_array(third.get(), 5);
std::unique_ptr<int[]> forth = del_element(std::move(third), 5, 4);
print_array(forth.get(), 4);
std::unique_ptr<int[]> fifth = del_element(std::move(forth), 4, 2);
print_array(fifth.get(), 3);
std::unique_ptr<int[]> sixth = del_element(std::move(fifth), 3, 1);
print_array(sixth.get(), 2);
std::unique_ptr<int[]> seventh = del_element(std::move(sixth), 2, 0);
print_array(seventh.get(), 1);
std::unique_ptr<int[]> eighth = del_element(std::move(sixth), 1, 0);
print_array(eighth.get(), 0);
最后但同样重要的是,请扔掉所有这些废话,使用std::vector
、std::deque
、std::list
或任何适合您的用例。它具有更多的功能和更少的错误。
【讨论】:
是的。这是学校的练习。不幸的是,我无法更改该功能。这就是为什么它听起来有点奇怪 嗯,这肯定是一个很好的 C 学校练习,但是从原始指针开始一个 C++ 类是(恕我直言)一个坏主意。原始指针不受欢迎的原因包括(但不限于)它们对异常安全的无知和零范围意识。相比之下,基于对象的“指针”(例如std::unique_ptr
)解决了这些问题。以上是关于删除元素后如何返回数组?的主要内容,如果未能解决你的问题,请参考以下文章
2021-09-20:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O