在C ++中返回Vector相当于c#

时间:2013-11-07 19:53:38

标签: c++ vector

我有很多C#代码,我必须用C ++编写。我在C ++方面没有太多经验。

我正在使用 Visual Studio 2012 进行构建。该项目是 C ++中的静态库(不在C ++ / CLI中)。

我知道这是一个基本问题,但我一直在阅读,我感到很困惑。 在C#代码中,他们在几个地方使用 double []数组,从他们使用它们的方式来看,我看到在C ++中替换它们的最佳方法是使用vector。

C#中有一些属性可以返回数组的副本,我想在C ++中做同样的事情。

注意:myArray是MyClass的成员。

C#

public double[] MyArray
    {
        get
        {
            /*** Some Code Here ***/
            double[] myCloneArray= (double[])myArray.Clone();
            return myCloneArray;
        }
    }

我想在C ++中完成类似的工作,但最大限度地减少了创建的副本数量。 这是正确的吗?

C ++

vector<double> MyClass::GetMyArray()
{   
      /*** Some Code Here ***/
      vector<double> myCloneArray= vector<double>(myArray);
      return myCloneArray;  
}

我只想创建一个myArray副本。由于我没有返回引用,我的理解是,在返回myCloneArray时,将创建它的副本。 这总是如此吗?

我想确定,所以我在互联网上阅读,但我很困惑,因为有些人说有些编译器没有这样做。

我想确保我总是发送副本,而不是相同的向量。我现在正在使用编译器,但最终我的代码也将在其他编译器中构建,所以我需要确保这不依赖于编译器

这是我能走的最佳方式吗?或者我可以减少代码,像这样:

C ++

vector<double> MyClass::GetMyArray()
{   
      /*** Some Code Here ***/
      return myArray;   
}

将调用vector(myArray)的复制构造函数吗?

2 个答案:

答案 0 :(得分:5)

您实际上不需要创建myCloneArray。只需返回myArray,它就会传递一份副本。这是每个编译器的情况。

通常,如果正在返回一个对象,并且它没有通过引用或作为指针返回,则将在类上调用复制构造函数,并将对象作为参数传递。唯一没有发生的情况是复制构造函数是否已被删除,在这种情况下,您发布的代码无论如何都不会编译。

C ++与C#或JAVA之间的不同之处在于,在C#和JAVA中,您实际上是返回一个指针,而不是复制(或移动)堆栈中的对象。如果你这样想,那么语言之间的行为是相同的。

答案 1 :(得分:3)

C ++在类分配方面与C#不同,因为它允许自动分配类,而C#要求每次都明确地实例化类。

用C ++编写时:

std::vector<int> * vec = new std::vector<int>();

C#中有一个等价物:

List<int> list = new List<int>;

但是如果你自动分配课程:

std::vector<int> vec;

你无法简单地将它翻译成C#(语言结构,我的意思)。

自动分配的类的行为与简单值的相同。因此 - 例如 - 当您通过参数将局部变量传递给函数时,它将通过值传递 - 这意味着它的值被复制到函数体。类似地,当您将通过参数自动分配的类传递给函数时,它也将被复制到类体。

当你从一个函数返回类实例时,存在类似的机制(通过值,就像你的情况一样 - 不是通过指针或引用)。正在制作该类的副本并将其返回给调用者,这样原始类保持不变(无论在何处以及如何分配)。

但是C ++ 11中有一个问题。从事C ++标准工作的人看到,如果你生成一个带有1000个元素的向量,然后从函数中返回它,那么这1000个元素必须被复制到另一个向量,它将从函数返回,然后原始载体正在被摧毁。这是一个巨大的不必要的性能损失。

这就是他们引入移动构造函数的原因。在所描述的情况下,从函数返回的副本的构造函数不复制元素,而只是从局部变量移动一些字段以访问这些元素(如数组指针)。本地变量在之后立即销毁,因此没有问题,只复制了一个指针 - 而不是1000个元素。

这种情况可能发生在现代C ++编译器中,但只有在编译器绝对确定的情况下,才会再使用从中复制数据的向量。因此,如果您要返回一个类别字段的向量,则编译器无法调用移动ctor。

现在,经过一些理论,让我们来看看你的代码。

vector<double> MyClass::GetMyArray()
{   
    vector<double> myCloneArray= vector<double>(myArray); // 1
    return myCloneArray; // 2
}

首先,准备myArray。然后,在(1)陈述中,您:

  • 通过调用vector<double>(myArray);
  • 显式创建该数组的临时副本
  • 然后,将该临时副本的内容复制到myCloneArray
  • 然后你返回myCloneArray并再次将它复制到从函数返回的结果中。

如果myArray是一个类字段,你可以做得更简单:

vector<double> MyClass::GetMyArray()
{   
    return myArray;
}