C++ 是否可以返回对std::vector中数据的引用,并在该向量超出范围后保留该引用?

C++ 是否可以返回对std::vector中数据的引用,并在该向量超出范围后保留该引用?,c++,memory,stdvector,C++,Memory,Stdvector,我习惯用C语言编程,在这种语言中,我只返回一个指向数据的指针,然后调用者将负责释放数据,然而,从我读到的内容中,向量的析构函数将在它超出范围时被调用,导致它的数据被取消分配 一旦返回了引用,内容的大小就不会改变,所以如果我能有一个指向数据的指针,然后手动删除,那将是理想的。我真正不想做的是将所有数据复制到一个新的容器中,因为这个向量将变得非常大 任何帮助都将不胜感激。到目前为止,我看到的每个解决方案都涉及到按值复制并依靠编译器对其进行优化,或者使用其他类来包装向量 编辑:为了清楚起见,我要保留的

我习惯用C语言编程,在这种语言中,我只返回一个指向数据的指针,然后调用者将负责释放数据,然而,从我读到的内容中,向量的析构函数将在它超出范围时被调用,导致它的数据被取消分配

一旦返回了引用,内容的大小就不会改变,所以如果我能有一个指向数据的指针,然后手动删除,那将是理想的。我真正不想做的是将所有数据复制到一个新的容器中,因为这个向量将变得非常大

任何帮助都将不胜感激。到目前为止,我看到的每个解决方案都涉及到按值复制并依靠编译器对其进行优化,或者使用其他类来包装向量


编辑:为了清楚起见,我要保留的向量的唯一部分是指向其数据的指针,即使用vector.data方法获得的指针,我不需要保留关于原始向量的任何其他信息。

引用的整个要点是它不拥有对象。在这里使用std::unique_ptr是完全有效的,它拥有对象并可以返回给调用方

您的函数定义如下:我假设一个整数向量,以及C++14或更高版本:

std::unique_ptr<std::vector<int>> getVector() {
    auto vec = std::make_unique<std::vector<int>>(/*any ctor args you want*/);
    // for example
    vec->push_back(1);
    vec->push_back(2);
    return vec;
}

引用的全部意义在于它不拥有对象。在这里使用std::unique_ptr是完全有效的,它拥有对象并可以返回给调用方

您的函数定义如下:我假设一个整数向量,以及C++14或更高版本:

std::unique_ptr<std::vector<int>> getVector() {
    auto vec = std::make_unique<std::vector<int>>(/*any ctor args you want*/);
    // for example
    vec->push_back(1);
    vec->push_back(2);
    return vec;
}

只需像这样编写代码:

std::vector<blah> my_function_that_returns_a_vector ()
{
    std::vector <blah> v;
    ... code to populate v ...
    return v;
}

然后将删除该副本。相反,返回的向量直接在调用方的堆栈框架中构造。

只需编写如下代码:

std::vector<blah> my_function_that_returns_a_vector ()
{
    std::vector <blah> v;
    ... code to populate v ...
    return v;
}

然后将删除该副本。相反,返回的向量直接在调用方的堆栈框架中构造。

对于您描述的用例来说,这是一个安全、快速的解决方案:不要返回引用,而是将向量返回到范围之外

是否可以返回对std::vector中数据的引用,并在该向量超出范围后保留该引用

是的。。。如果使用静态存储。具有静态存储持续时间的对象的生存期将一直延长到程序结束。因此,当它们超出范围时,它们仍然活着。请注意,静态存储是全局状态的,这通常是有问题的。如果可以避免,请小心使用

自动存储:否

我只返回一个指向数据的指针,然后调用方将负责释放数据

这是一个有问题的方法。调用方如何知道他们负责释放数据?调用方如何知道如何释放数据?如果有其他数据用户,调用方如何知道何时可以释放数据?这一切都依赖于调用者阅读文档、理解文档,而不是犯错误。这是许多内存泄漏、通过无效指针进行访问和双重释放崩溃的根源

向量在某种程度上解决了这些问题;C或C++中没有接口,如果一个人通过将生命周期与容器对象保持联系来进行足够的努力,就不会被滥用。 如果我能有一个指向数据的指针,然后手动删除,那将是理想的


你不能那样。std::vector始终会破坏其数据,并且除了通过移动或交换将数据窃取到另一个vector之外,不可能将数据窃取到vector的外部。

对于您描述的用例来说,这是一个安全、快速的解决方案:不要返回引用,而是将vector返回到作用域的外部

是否可以返回对std::vector中数据的引用,并在该向量超出范围后保留该引用

是的。。。如果使用静态存储。具有静态存储持续时间的对象的生存期将一直延长到程序结束。因此,当它们超出范围时,它们仍然活着。请注意,静态存储是全局状态的,这通常是有问题的。如果可以避免,请小心使用

自动存储:否

我只返回一个指向数据的指针,然后调用方将负责释放数据

这是一个有问题的方法。调用方如何知道他们负责释放数据?调用方如何知道如何释放数据?如果有其他数据用户,调用方如何知道何时可以释放数据?这一切都依赖于调用者阅读文档、理解文档,而不是犯错误。这是许多内存泄漏、通过无效指针进行访问和双重释放崩溃的根源

向量在某种程度上解决了这些问题;没有国际文传电讯组织 C或C++中的CES,如果一个人通过将生命周期绑定到容器对象来进行足够的努力,就不会被滥用。

如果我能有一个指向数据的指针,然后手动删除,那将是理想的


你不能那样。std::vector始终会破坏其数据,并且不可能将数据窃取到向量外部,除非通过移动或交换将数据窃取到另一个向量。

不可能在向量超出范围后保留对该向量的引用,因为正如您所提到的,它将被删除。一旦向量被删除,存储在该地址的内存将无法访问。或者,您可以在范围外声明变量,在范围内编辑变量。您提到通过引用返回-是否可以通过引用将向量传递到函数中,然后简单地返回void?通过这种方式,您可以在不同的范围内编辑同一个向量。

在向量超出范围后不可能保留对该向量的引用,因为正如您所提到的,它将被删除。一旦向量被删除,存储在该地址的内存将无法访问。或者,您可以在范围外声明变量,在范围内编辑变量。您提到通过引用返回-是否可以通过引用将向量传递到函数中,然后简单地返回void?通过这种方式,您可以在不同的范围内编辑相同的向量。

引用的整个要点是它不拥有对象。在这里使用std::unique\u ptr是完全有效的。不,尽管您可以查看智能指针。在C++中,它将被复制,或简单地返回到一个可能带有移动构造的对象。参见STD::vector和标准库中的大多数容器支持移动语义。如果您有一个类似std::vector getData的函数。。。{std::vector result;//生成数据;返回结果;}结果被移动而不是复制。这不是编译器优化。因此,有时返回指针是不必要的。@KennyOstrom我认为这与我的问题不太一样,因为在这种情况下,它们返回的是一个向量,而在我的情况下,函数确实需要返回一个原始指针。引用的全部要点是它不拥有对象。在这里使用std::unique\u ptr是完全有效的。不,尽管您可以查看智能指针。在C++中,它将被复制,或简单地返回到一个可能带有移动构造的对象。参见STD::vector和标准库中的大多数容器支持移动语义。如果您有一个类似std::vector getData的函数。。。{std::vector result;//生成数据;返回结果;}结果被移动而不是复制。这不是编译器优化。所以,有时返回一个指针是不必要的。@KennyOstrom我不认为这与我的问题是一样的,因为在这种情况下,他们返回的是一个向量,在我的例子中,函数确实需要返回一个原始指针。调用者知道如何释放数据,因为调用者已经在编写函数时期望该函数将生成一个指针。数据本身只是一堆原语。你确定没有办法窃取数据吗?我不在乎原始向量之后是否不可用,因为它将立即超出作用域。@TrevorGalivan调用者知道释放数据,因为调用者已经在编写时期望此函数将生成指针。并不是所有的指针都应该被调用方释放。strtok你确定没有办法窃取数据吗?好的,谢谢。如果我返回向量本身,数据会被深度复制吗?或者它保证数据保持在适当的位置,并且只复制向量的其他属性?@TrevorGalivan数据最终会被深度复制吗?不可以。如果复制了任何内容,则将通过移动,即浅复制。在向量的情况下,需要复制大约24个字节,其他一些字节设置为零。但是几乎所有的编译器都会省略移动,这样就不会复制任何内容。调用者知道如何释放数据,因为调用者已经在编写该函数时预期该函数将生成指针。数据本身只是一堆原语。你确定没有办法窃取数据吗?我不在乎原始向量之后是否不可用,因为它将立即超出作用域。@TrevorGalivan调用者知道释放数据,因为调用者已经在编写时期望此函数将生成指针。并不是所有的指针都应该被调用方释放。strtok你确定没有办法窃取数据吗?好的,谢谢。如果我返回向量本身,数据会被深度复制吗?或者它保证数据保持在适当的位置,并且只复制向量的其他属性?@TrevorGalivan数据最终会被深度复制吗?不,如果有什么是c
如果没有,它将通过移动,即浅拷贝。在向量的情况下,需要复制大约24个字节,其他一些字节设置为零。但几乎所有的编译器都会省略这一动作,这样就不会复制任何东西。虽然它在技术上可以满足OP的要求,但我认为没有理由动态分配这样的向量。虽然它在技术上可以满足OP的要求,我认为没有理由动态分配这样的向量。值得指出的是,NVRO依赖于编译器和设置,因此无法保证。但是,如果您使用的是C++11或更高版本,那么移动语义将或多或少地完成相同的工作:std::vector有一个移动构造函数,您只需要确保blah类也有。值得指出的是,NVRO依赖于编译器和设置,因此无法保证。但是,如果您使用的是C++11或更高版本,那么移动语义将或多或少地完成相同的工作:std::vector有一个移动构造函数,您只需要确保blah类也有。