【问题标题】:Is it better to return a vector<int> or an int*?返回 vector<int> 还是 int* 更好?
【发布时间】:2016-09-21 10:26:02
【问题描述】:

我有一个方法应该返回一些整数。这些整数将在构造函数之后使用。由于我对指针不太满意,所以我决定使用向量作为返回类型,以便稍后在 myObject 的构造函数中使用 myVector[i] 访问不同的整数。

但是我的同事说在这种情况下将 int* 作为返回类型更好,因为“如果要返回容器,那么您最好返回一个 myObject 类型并直接在方法中实例化它”。

所以在这种情况下,使用指针似乎更好。这是真的吗?那为什么?

编辑:好的,我会在这里详细说明。

这是我的具有三个 int 属性的类:

class MyClass{

public:
MyClass(int x, int y, int s);

private:
int coord_x;
int coord_y;
int size;
}

在另一个 .cpp 文件中,我有这样的方法:

// FileWithMethod.cpp
vector<int> myMethod(){

// some code here
return my_vector;
}

my_vector 有 3 个 int 并且总是如此,因为它的元素将用于在第二个 .cpp 文件中实例化一个 MyClass 对象。

这里的讨论是 myMethod() 的返回类型应该是 int* 还是向量。我的同事建议使用 int* ,因为“实现这种结构是没有用的(即返回参数的方法,稍后将在构造函数中使用)”。他为什么这么说,我不知道。他说如果我们使用指针,这个结构很有趣,但如果我们使用容器,那么最好直接返回一个用 3 int 实例化的 MyClass 对象。因此,他似乎显然反对向量的想法,可能是在内存分配/管理方面,并且更喜欢对 MyClass 对象使用 int* 。

在这里,我认为 C++ 的主要资产是摆脱棘手的指针,仅在没有其他选择或性能差异不可忽略时才使用它们。

我希望这能更清楚地说明情况。抱歉解释模糊。我很难估计所提供的细节数量是否足以在您处理问题并且没有外部视角时理解问题:)。

感谢您的回答,他们已经很有帮助了!

【问题讨论】:

  • 认为我几乎明白你在说什么,但这个问题很模糊。您能否提供代码示例,并提供您选择的“更好”定义?对于它的价值,返回一个向量是一个很好的默认位置,因为它很简单并且对数据所有权没有任何疑问,但我不清楚你同事的建议是否打破了这一点,或者只是提出了一种更好的填充向量的方法。无论哪种方式,目前都没有可以安全地给出这个问题的包罗万象的答案。也就是说,取决于
  • 我猜你同事的意思是你在函数中构造对象并返回对象而不是硬币容器(或 int*)。容器的优点是您知道其中有多少元素。如果你只返回和int*你不知道元素的数量。
  • @Shahriyar,使用原始数组并不比使用向量更快,也不是更有效。但它更难,更容易出错。
  • 直接返回一个myObject而不是其构造函数的参数是有问题的,如果以后你可能想创建一个myDerivedObject
  • @Shahriyar:他们更难合理化和证明行为。这是客观事实。不管你有多聪明。没有必要“离开 C++”,因为至少在过去的二十年里,使用标准容器在 C++ 中一直是惯用且司空见惯的。 C++ 不是 C。而且,不,它并没有更高效。如果您要比较动态分配与非动态分配,那很好,但要诚实。

标签: c++ pointers vector


【解决方案1】:

由于您总是准确返回 3 个ints,这是一个足够小的数字,因此请考虑使用std::array&lt;int, 3&gt;

它可能是最有效的,当然也是最受限制的标准类型。

【讨论】:

  • 我不知道C++中存在数组类型(以为是用vector代替了)。我会试一试。谢谢!
  • std::vectorstd::array 都有各自的用例。 vector 是用来替换动态大小的数组,array 是用来替换固定大小的数组。
【解决方案2】:

从您同事的引述中,我认为他建议返回您要实例化的对象,而不是 vector,而不是 int*。这意味着如果这个返回值的唯一目的是作为另一个对象的构造函数的输入,为什么不在这个函数中构造对象并跳过临时结构。

在你的例子中是:

MyClass myMethod(){    
    // some code here
    return MyClass{ /* my_vector values */ };
}

也就是说,返回指向数组的指针(我假设您的意思是 int*)可能不是一个好主意,因为您必须在以后跟踪谁应该是 delete(在 MyClass 之后)建造)。在这方面,标准容器更可取。

如果您不想使用vector,因为它对性能的影响很小(无论如何,您都应该考虑使用 IMO)并且无法在方法中实例化目标类,也许还有另一种方法。例如,我会使用 tuple&lt;int, int, int&gt; 作为返回值。它比原始的类 c 数组非常轻巧且易于使用。如果将来参数数量发生变化,则维护起来并不容易。

【讨论】:

  • 问题是这里我们需要将 myMethod() 之类的方法(即返回未来构造函数参数的方法)和 MyClass 之类的类(即其构造函数将使用myMethod()) 和将使用所有这些的 .cpp 文件。简而言之,我们有 .cpp 文件来存储诸如 myMethod() 之类的方法,.cpp 文件来存储诸如 MyClass 之类的类,以及一个 .cpp 文件来调用方法并实例化 MyClass 对象(例如“main.cpp”,但没有主)。所以通常instatiation发生在类似“main.cpp”的文件中。
  • 我的同事说的是“如果这个返回值的唯一目的是作为另一个对象的构造函数的输入,为什么不在这个函数中构造对象并跳过临时结构?这样会更好但由于我们在 main-like 文件中实例化对象,因此您不应该在方法中这样做。因此使用 int*"
  • @SoniaSeddiki 也许你会对tuple 感兴趣?查看我的编辑
  • 使用元组会很好,但是tuple&lt;int, int, int&gt;array&lt;int, 3&gt; 之间有什么区别?我知道我在这里很挑剔,但这一次更多的是为了我的个人文化而不是真正的表现问题。希望你不介意:)!
  • @SoniaSeddiki 老实说,我认为这两者之间没有太大区别。例如this question 将其视为更多语义基础。选择您感觉更好的使用;)
【解决方案3】:

AFAIK,从方法或函数返回标准容器很好。除非您已经知道这将是一个使用非常广泛的功能,并且确实需要低级优化,否则在早期开发阶段拒绝它在我看来是不成熟的优化。

正如@LightnessRacesinOrbit 在 cmets 中所解释的那样,由于数据的动态分配和初始化,使用向量会增加一些开销。如果你真的需要这样的低级优化,我会在调用者中声明 3 个变量并通过引用传递它们。这样你就没有返回悬空指针的风险,没有线程安全问题(如果你使用静态数组来避免悬空指针问题,可能会出现),也没有不必要的动态分配。只需使用:

void myMethod(int& x, int& y, int& s) {
    ...
}

恕我直言,直接返回 MyClass 对象可能(取决于一般设计)在模块之间添加不需要的依赖关系。

【讨论】:

  • 我不确定这里的性能成本。我们正在研究计算机视觉。我们必须分析 30 到 60 fps 的视频流,并在每一帧都使用这些方法。我们的目标是进行多线程图像处理,但目前并非如此。
猜你喜欢
  • 2013-08-30
  • 2013-08-20
  • 2018-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 2011-12-20
相关资源
最近更新 更多