【问题标题】:Return vector from function without it being destroyed从函数返回向量而不被破坏
【发布时间】:2011-06-26 11:16:09
【问题描述】:

我遇到了一个有趣的问题。我在 C++ 中有一个函数,它返回一个充满类的向量。返回向量后,它会为向量中的每个元素调用解构函数。

问题很明显:数据在类指向指针的地方被销毁,当对象被销毁时这些指针被释放。我只能假设调用解构函数是因为向量在堆栈上,而不是在堆上。

所以问题是:

有没有办法继续从函数返回向量,而不被破坏?还是我必须传递一个指针以返回向量作为函数的输入?

【问题讨论】:

  • 您是否返回了对临时对象的引用?我不太清楚你在描述什么。源代码?
  • @sstn:我返回一个完整的向量,而不是指向它的指针。
  • 我假设您解决了您的问题 - 但只能在没有看到实际代码的情况下进行推测。顺便说一句,引用不是指针。

标签: c++ heap-memory stack-memory


【解决方案1】:

您可以使用new 在堆上创建任何东西。您不应该从函数中给出对堆栈对象的引用,因为它们将在函数完成后立即被销毁。

如果您希望您的函数按值返回向量,请确保向量内的对象实现了复制构造函数(也许还有赋值运算符,对此不确定)。有了这个,请不要忘记Rule of Three

【讨论】:

  • 可以使用 std::vector result = new std::vector(); 吗?
  • @Alex:不,你需要std::vector<int>* pResult = new std::vector<int>();。您需要以pResult->push_back(...) 而不是result.push_back(...) 的身份访问您的向量。
  • 这就是我想知道是否还有另一种方法,而不仅仅是指针。虽然我猜它无论如何都应该是指针,因为它会更好地消耗内存。
  • @Alex:另一种方法是函数将向量作为参数(指针或引用),并用内容填充它。从资源管理的角度来看,这种方式实际上可能更好:您不需要关心堆上向量的释放。
【解决方案2】:

C++11 应该使用右值引用解决您的问题。老实说,我自己没有尝试过,但是从我读到的内容来看,它将完全按照您的要求返回向量而不破坏和重新创建它(通过将该向量分配的内存传递给新向量而不是让新向量创建自己的内存并从旧向量复制内容)。

【讨论】:

  • 即使没有 C++11,编译器也有可能会执行 return value optimization 并避免复制。除非您确定它们确实被使用,否则很难推荐神奇的编译器优化。
【解决方案3】:

C++ 向量 分配在堆上。当您按值返回向量时,将使用所有元素的副本创建一个新向量,然后将销毁原始元素。

听起来你没有正确定义你的复制构造函数。例如:

class ThisIsWrong
{
public:
    ThisIsWrong()
    {
        i = new int;
        *i = rand();
    }
    ~ThisIsWrong()
    {
        delete i;
        i = nullptr;
    }

    int value() const
    {
        return *i;
    }

private:
    int* i;
};

void foo()
{
    vector<ThisIsWrong> wronglets;
    wronglets.push_back(ThisIsWrong());
    return wronglets;
}

void main()
{
    vector<ThisIsWrong> w = foo();
    w[0].value(); // SEGFAULT!!
}

您要么需要删除复制和赋值构造函数(这将把它变成编译错误而不是运行时),要么正确实现它们。

【讨论】:

    猜你喜欢
    • 2020-02-17
    • 1970-01-01
    • 2020-07-18
    • 2021-10-26
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多