如何在方法体中返回已声明向量的引用?

我有这种方法:

vector<float> myobject::getResults(int n = 1000)
{
    vector<float> results(n,0);
    // do some stuff
    return results;
}

当然,这不是经过优化的,我想返回该向量的引用,但我不能简单地这样做:

const vector<float>& myobject::getResults(int n = 1000)
{
    vector<float> results(n,0);
    // do some stuff
    return results;
}

这是行不通的,因为向量是局部变量,所以向量将在方法结束时销毁。

因此,我发现解决此问题的唯一方法是在myobject中创建一个私有向量并返回对该向量的引用:

const vector<float>& myobject::getResults(int n = 1000)
{
    this->results.clear();
    this->results.resize(n,0);
    // do some stuff
    return results;
}

这是正确的方法吗?您还有其他解决方案可以提出吗?

zhaoyp2222 回答:如何在方法体中返回已声明向量的引用?

最有效的是什么?

按值返回。不用担心,不会发生复制。这是最佳做法:

// Use this
vector<float> getResults(int n = 1000);

这是为什么?不会复制从函数返回的局部变量。它们被移到将存储返回值的位置:

// Result moved into v; no copying occurs
vector<float> v = getResults(); 

// Result moved into memory allocated by new; no copying occurs
vector<float>* q = new vector<float>(getResults()); 

这是如何工作的?

当函数返回一个对象时,它以两种方式之一返回它:

  • 在寄存器中
  • 在内存中

您只能在寄存器中返回简单对象,例如intdouble。对于在内存中返回的值,该函数将传递一个指针,该指针指向放置返回值所需的位置。

致电new vector<float>(getResults());时,会发生以下情况:

  • 计算机为新的向量分配内存
  • 它将该内存的位置以及任何其他参数提供给getResults()
  • getResults在该内存中构造向量 ,无需复制。

如何返回对成员变量的引用?

通常来说,这是过早的优化可能不会提供太多或任何好处,并且它会使您的代码更复杂,更容易错误

如果将getResults的输出分配给矢量,则数据将始终被复制:

MyObject m; 
vector<float> = m.getResults(); // if getResults returns a const reference,the data gets copied

另一方面,如果将getResults的输出分配给const reference,则管理MyObject的生存期会变得更加复杂。在下面的示例中,由于函数m被销毁,因此函数返回后,您返回的引用就会失效

vector<float> const& evilDoNotUseThisFunction() {
    MyObject m;
    vector<float> const& ref = m.getResults();
    return ref; // This is a bug - ref is invalid when m gets destroyed
}

std::vector复制和移动有什么区别?

复制遍历向量的所有元素。复制向量时,向量存储的所有数据都将被复制:

vector<float> a = getVector(); // Get some vector

vector<float> b = a // Copies a

这等效于以下代码:

vector<float> a = getVector(); // Get some vector

vector<float> b(a.size()); // Allocate vector of size a

// Copy data; this is O(n)
float* data = b.data();
for(float f : a) {
    *data = f;
    data++;
}

移动不会在任何元素上循环。move构造向量时,就好像它被替换为空向量一样:

vector<float> a = getVector(); // Get some vector

vector<float> b = std::move(a); // Move a into b

等效于:

vector<float> a = getVector(); // Get some vector

vector<float> b; // Make empty vector (no memory allocated)

std::swap(a,b); // Swap a with b; very fast; this is O(1)

TL; DR:复制将循环复制所有数据。移动只是交换出谁拥有内存。

我们怎么知道results被移动? C ++ 11要求局部变量在返回时自动移动。您不必致电move

交换是否确实发生?在许多情况下,不会。交换已经很便宜,但是编译器可以很聪明,可以完全优化交换。通过在要返回{{1的内存中构造您的results向量}}。这称为命名返回值优化。参见https://shaharmike.com/cpp/rvo/#named-return-value-optimization-nrvo

,
  

当然这不是最佳的

很好。具体来说,由于使用C ++ 11,因此您无需在此处做任何额外的事情。

无论如何,只有在拥有正确的东西以及分析它的方法之后,您才应该担心优化。

无论如何,返回对私有向量的引用并不理想-它不必要地延长了向量的寿命,并且像其他任何有状态函数一样,稍后可能会导致重新进入问题。

本文链接:https://www.f2er.com/3027327.html

大家都在问