【发布时间】:2019-04-21 04:10:49
【问题描述】:
我正在尝试解决Leetcode Problem 22(这只是一个非常简单的递归应用程序),并且我试图记住结果以加快计算速度。但是,当我尝试存储指向向量的指针列表时,我遇到了std::bad_alloc 错误,而当我只是存储指针列表时,程序运行良好。我对 C++ 和指针和内存分配比较陌生,所以这可能是一个非常愚蠢的问题,但我已经看了一段时间的代码,但似乎无法弄清楚。
所以,这是代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
vector<string> generateParenthesis(int n) {
if (n == 0) {
return {};
}
return generateParenthesis_recursive(n);
}
vector<vector<string>*> memo;
vector<string> generateParenthesis_recursive(unsigned int n) {
if (n < memo.size()) {
return *(memo[n]);
}
vector<string> result;
if (n == 0) {
result = {""};
}
else if (n == 1) {
result = {"()"};
}
else if (n > 1) {
vector<string> left, right;
for (unsigned int k = 0; k < n; k++) {
left = generateParenthesis_recursive(k);
right = generateParenthesis_recursive(n - k - 1);
for (auto left_parenths : left) {
for (auto right_parenths : right) {
result.push_back("(" + left_parenths + ")" + right_parenths);
}
}
}
}
while (memo.size() <= n) {
memo.push_back(nullptr);
}
memo[n] = &result;
return result;
}
};
int main(int argc, char const *argv[]) {
Solution s;
vector<string> output = s.generateParenthesis(4);
for (auto s : output) {
cout << s << " ";
}
cout << endl;
return 0;
}
我不太确定在哪里或为什么,但这会引发 std::bad_alloc 错误。但是,将 memo 更改为 vector<vector<string>>(并更改代码的其他各个小部分以使其有意义),它可以正常工作。
具体是什么导致了这里的错误?没有无限循环,递归有一个明确定义的基本情况,我不认为我分配了太多内存。我看不出程序如何分配内存失败。
【问题讨论】:
-
memo[n] = &result;无效,因为result是该函数内的局部变量,这意味着它的生命周期在函数结束时结束,并且指针无效。 -
不使用指针?首先要专注于编写有效的优秀代码。然后,如果性能不够好(通常足够足够好),则分析和测量以找到瓶颈。修复一个并再次测量以找到下一个。而且由于优化往往会使代码难以阅读和理解(因此难以维护),因此请编写 cmets 了解优化后的代码在做什么以及为什么要这样做。
-
并通过 const& 返回您的向量,复制它们的成本很高!
-
@MatthieuBrucher ...而且移动起来相当便宜,如果 NRVO 启动,甚至免费。在这种情况下,它们不能由 & 返回,因为它们是在局部变量中计算的结果。跨度>
-
@Marc.2377 当然,继续!永远不要妨碍对正确信息的追求!