2

我有一个简单的函数,我简化为只返回一个虚拟列表(以确保它不是一些逻辑错误)

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消息打印正确的大小 2,它也始终为 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;
}
4

3 回答 3

4

您正在从函数返回一个临时地址getCandidateList,该对象在函数返回时释放。访问它是未定义的行为。您可以只返回向量,RVO应该来应用并删除副本:

尝试:

std::vector<AttrValue> QueryEvaluator::getCandidateList(...) 
{
  //blah
  return values; 
}

我尝试了一个简单的程序,它似乎很好......

getCandidateList 函数返回时释放临时向量。该程序具有未定义的行为。

于 2013-01-25T11:00:25.297 回答
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(...) {
于 2013-01-25T11:00:05.400 回答
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;
}

边注:

Also you need to try not to use pointers in your code. Pointers doe not convey any ownership.This means we do not know who is responsible for deleting the object. In this case a reference would probably have been better (you never return NULL) as this gives the caller access to the object will retaining ownership (assuming you decided not to return by value).

于 2013-01-25T11:21:23.773 回答