C++ 在C+;中的函数中动态分配大结构时选择的返回值+;

C++ 在C+;中的函数中动态分配大结构时选择的返回值+;,c++,return-value,smart-pointers,C++,Return Value,Smart Pointers,假设我的函数: vector<MyClass>* My_func(int a) { vector<MyClass>* ptr = new vector<MyClass>; //...... Add a lot of elements to this vector, and let's say MyClass is also relatively big structure. return ptr; } vector*My_func(

假设我的函数:

vector<MyClass>* My_func(int a)
{
    vector<MyClass>* ptr = new vector<MyClass>;
    //...... Add a lot of elements to this vector, and let's say MyClass is also relatively big structure.

    return ptr;
}
vector*My_func(int a)
{
向量*ptr=新向量;
//……给这个向量添加了很多元素,比如说MyClass也是一个比较大的结构。
返回ptr;
}
此方法让用户负责释放指针

我能想到的另一种方法是在函数中创建局部变量并返回值:

vector<MyClass> My_func(int a)
    {
        vector<MyClass> vec;
        //...... Add a lot of elements to this vector, and let's say MyClass is also relatively big structure.

        return vec;
    }
向量My_func(int a) { 向量向量机; //……给这个向量添加了很多元素,比如说MyClass也是一个比较大的结构。 返回向量; } 这种方法避免了用户的责任,但在返回和复制值时可能会占用大量空间

也许C++中的智能指针是更好的选择,但我不确定。我以前没有使用智能指针。人们遇到这种情况时会怎么做?他们会选择什么样的退货类型


感谢前面的提示:-)

在许多情况下,返回值优化可以轻松处理不必要的复制。问题是:你打算如何在函数之外使用这个向量?如果您有以下情况:

vector<MyClass> ret = My_func(a);
 void My_func(int a, vector<MyClass>& vec)
 {
   ... 
 }

此外,这还改变了函数的语义(例如,您可能需要清除向量)。

在许多情况下,返回值优化可以轻松处理不必要的复制。问题是:你打算如何在函数之外使用这个向量?如果您有以下情况:

vector<MyClass> ret = My_func(a);
 void My_func(int a, vector<MyClass>& vec)
 {
   ... 
 }

此外,这还改变了函数的语义(例如,您可能需要清除向量)。

在这种构造的大多数情况下,编译器将执行“返回值优化”,这意味着它实际上没有复制要返回的数据结构,而是直接写进一个生活在它将被送回的地方

因此,您可以安全地执行此操作,而无需担心它被复制

但是,另一种方法是不首先返回向量,而是请求调用代码传入一个:

比如说:

vector<MyClass> ret = My_func(a);
 void My_func(int a, vector<MyClass>& vec)
 {
   ... 
 }
void My_func(int a、vector和vec)
{
... 
}

这可以保证避免复制

在这种构造的大多数情况下,编译器将执行“返回值优化”,这意味着它实际上不是复制要返回的数据结构,而是直接写入要返回的位置上的数据结构

因此,您可以安全地执行此操作,而无需担心它被复制

但是,另一种方法是不首先返回向量,而是请求调用代码传入一个:

比如说:

vector<MyClass> ret = My_func(a);
 void My_func(int a, vector<MyClass>& vec)
 {
   ... 
 }
void My_func(int a、vector和vec)
{
... 
}

这可以保证避免复制

这是向量的内部结构

template <typename T>
class vector {
private:
  size_t m_size;
  size_t m_cap;
  T * m_data;
public:
//methods push pop etc.
};
模板
类向量{
私人:
大小;
尺寸m____帽;
T*m_数据;
公众:
//方法推送pop等。
};
正如您所能看到的,向量的大小(还有两个额外的大小数据成员)并不比指针的大小大多少。在传递向量而不是指针时,性能上的好处可以忽略不计,事实上,使用指针时,访问向量的速度会较慢,因为每次都必须取消对指针的引用。通常,我们不创建指向向量的指针


另外,永远不要返回指向局部变量的指针。一旦返回值并超出方法的范围,局部变量的内存将被清除。理想情况下,在调用方法My_func时,应该在调用函数中创建一个向量,并传递对该向量的引用。

以下是向量的内部结构

template <typename T>
class vector {
private:
  size_t m_size;
  size_t m_cap;
  T * m_data;
public:
//methods push pop etc.
};
模板
类向量{
私人:
大小;
尺寸m____帽;
T*m_数据;
公众:
//方法推送pop等。
};
正如您所能看到的,向量的大小(还有两个额外的大小数据成员)并不比指针的大小大多少。在传递向量而不是指针时,性能上的好处可以忽略不计,事实上,使用指针时,访问向量的速度会较慢,因为每次都必须取消对指针的引用。通常,我们不创建指向向量的指针


另外,永远不要返回指向局部变量的指针。一旦返回值并超出方法的范围,局部变量的内存将被清除。理想情况下,在调用方法My_func时,您应该在调用函数中创建一个向量,并传递对该向量的引用。

您可能需要了解,以及。简而言之,按值返回向量不会有问题。您可能想了解的可能重复项,以及。简言之,按值返回向量不会有问题。在我看来,引用的使用将完全避免应用程序进行复制。正如@MatsPetersson在他的回答中所说,使用引用作为参数肯定会避免任何副本。在我看来,使用引用将完全避免应用程序所做的副本。正如@MatstPeterson在他的回答中所说,使用引用作为参数肯定会避免任何复制。