不让函数返回的向量被销毁的方法

6
我遇到了一个有趣的问题。我有一个在C++中返回填充有类的向量的函数。一旦向量被返回,它就会调用向量中每个元素所对应的类的析构函数。
问题很明显:数据被销毁时,指针所指向的类也会被释放,因为这些指针是在对象被销毁时释放的。我猜想析构函数被调用的原因是向量位于栈上,而不是堆上。
所以问题是:
有没有办法保持从函数返回向量,而不销毁它?或者我必须通过将向量的指针作为输入参数传递给函数来解决这个问题?

1
你是在返回一个临时对象的引用吗?我不太清楚你所描述的内容。源代码呢? - sstn
@sstn:我返回整个向量,而不是指向它的指针。 - Alex
我假设你已经解决了你的问题 - 但是如果没有看到实际的代码,只能进行推测。顺便说一下,引用不是指针。 - sstn
3个回答

4
您可以使用new在堆上创建任何东西。不应该从函数中返回对堆栈对象的引用,因为它们将在函数完成时被销毁。
如果您希望函数通过值返回向量,请确保向量内部的对象实现了复制构造函数(也许还需要赋值运算符,不确定)。此外,请不要忘记遵守“三大法则”。详情请见这里

能否使用std::vector<int> result = new std::vector<int>();来实现? - Alex
3
@Alex: 不,你需要使用 std::vector<int>* pResult = new std::vector<int>();。然后你需要用 pResult->push_back(...) 而不是 result.push_back(...) 来访问你的向量。 - Vlad
这就是我想知道的,是否有其他方法可以做到这一点,而不仅仅是指针。虽然我猜它应该是指针,因为这样对于内存消耗来说会更好。 - Alex
2
@Alex:另一种方法是将向量作为参数(指针或引用)传递给函数,并填充其内容。从资源管理的角度来看,这种方式实际上可能更好:您不需要关心堆上向量的释放。 - Vlad

1

C++11应该可以通过使用右值引用来解决您的问题。说实话,我自己还没有尝试过,但从我所读到的内容来看,它将会完全做到您想要做的事情,即返回向量而不销毁和重新创建它(通过将由该向量分配的内存传递给新向量,而不是让新向量创建自己的内存并从旧向量复制内容)。


2
编译器有可能会执行返回值优化并避免复制,即使没有使用C++11。除非你确信它们确实被使用,否则很难推荐使用神奇的编译器优化。 - Mark Ransom

0

C++向量(Vectors)在堆上分配。当你通过值返回一个向量时,将创建一个新的向量,并复制所有元素,然后原始元素将被销毁.

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

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!!
}

你需要删除复制和赋值构造函数(这将使其成为编译错误而不是运行时错误),或者正确实现它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接