我有一个简单的函数,我简化为只返回一个虚拟列表(以确保它不是一些逻辑错误)
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
...
values.clear();
values.push_back(2);
values.push_back(3);
cout << "values is of size " << values.size() << endl;
return &values;
}
然后在cppunit测试中:
vector<AttrValue>* candidateList0 = evaluator->getCandidateList(cl, 0);
cout << candidateList0->size() << endl;
但问题是size()
,在测试中,即使cout
消息打印出正确的大小,也总是为0。可能出错了什么?
我尝试了一个简单的程序,看起来很好......
#include <iostream>
#include <vector>
using namespace std;
vector<int>* test() {
vector<int> vec { 2, 3, 6, 1, 2, 3 };
return &vec;
}
int main() {
cout << test()->size() << endl;
return 0;
}
答案 0 :(得分:4)
您正在从getCandidateList
函数返回临时地址,该函数返回时该对象将被释放。访问它是未定义的行为。您可以退出向量,RVO应该应用并删除副本:
尝试:
std::vector<AttrValue> QueryEvaluator::getCandidateList(...)
{
//blah
return values;
}
我尝试了一个简单的程序,看起来很好......
当getCandidateList函数返回时释放临时向量。该程序有不确定的行为。
答案 1 :(得分:2)
您的向量似乎在堆栈中声明,因此当它超出范围时(当函数退出时)将被销毁。如果要返回指向向量的指针,请将其分配给堆
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
vector<AttrValue>* values = new vector<AttrValue>();
...
values->clear();
values->push_back(2);
values->push_back(3);
cout << "values is of size " << values->size() << endl;
return values;
}
可能更容易在调用者中声明它并传递对getCandidateList
的引用
void QueryEvaluator::getCandidateList(vector<AttrValue>& values)
...或按值返回
vector<AttrValue> QueryEvaluator::getCandidateList(...) {
答案 2 :(得分:1)
要考虑很多有趣的事情:
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
...
values.clear();
values.push_back(2);
values.push_back(3);
cout << "values is of size " << values.size() << endl;
return &values;
}
所以看起来你遗漏了上面代码 ... 中最有趣的部分。故事的道德尝试并提供显示错误的可编译的工作代码。将问题简化为一个小例子通常会导致您自己发现问题。至少你应该提供所有使用对象的确切定义(类型是C ++中最重要的东西)
它是否将向量声明为本地对象?
std::vector<int> values;
在这种情况下,向量生命周期与函数绑定,并在函数结束时被销毁。这意味着在函数返回后使用它是未定义的行为(任何事情都可能发生)。
但是看起来你也在使用对象作为单元测试框架的一部分。因此,潜在的解决方案是使向量成为对象的一部分。然后,只要对象(不仅仅是函数调用)并且因此返回指向它的指针将按预期工作,矢量将存活。
class QueryEvaluator
{
std::vector<int> values;
public:
vector<AttrValue>* QueryEvaluator::getCandidateList(...);
};
另一种方法是按值而不是指针返回向量。这意味着该对象将被正确地复制出函数,并且您的调用代码可以操作并测试它们所需的所有向量。
vector<AttrValue> QueryEvaluator::getCandidateList(...)
{
...
return &values;
}
此外,您还需要尝试不在代码中使用指针。指针不传达任何所有权。这意味着我们不知道谁负责删除该对象。在这种情况下,引用可能会更好(您永远不会返回NULL),因为这使得调用者对该对象的访问将保留所有权(假设您决定不按值返回)。