数组:存储对象或引用

use*_*652 5 c++

作为Java开发人员,我有以下C++问题.

如果我有类型A的对象并且我想将它们的集合存储在数组中,那么我应该只存储指向对象的指针还是更好地存储对象本身?

在我看来,最好存储指针,因为:1)通过将其指针设置为null,可以轻松删除对象2)节省空间.

Fle*_*exo 7

指针或只是对象?

您不能在C++中将引用放入数组中.你可以创建一个指针数组,但我仍然更喜欢容器和实际对象而不是指针,因为:

  1. 没有机会泄漏,异常安全更容易处理.
  2. 它不是空间 - 如果你存储一个指针数组,你需要对象的内存加上指针的内存.

我主张在容器(或数组,如果你必须)中放置指针(或智能指针会更好)的唯一时间是你的对象不是可复制的可构造和可分配的(对容器的要求,指针总是满足这个)或你需要它们是多态的.例如

#include <vector>

struct foo {
  virtual void it() {}
};

struct bar : public foo {
  int a;
  virtual void it() {}
}; 

int main() {
  std::vector<foo> v;
  v.push_back(bar()); // not doing what you expected! (the temporary bar gets "made into" a foo before storing as a foo and your vector doesn't get a bar added)
  std::vector<foo*> v2;
  v2.push_back(new bar()); // Fine
}
Run Code Online (Sandbox Code Playgroud)

如果你想沿着这条道路向下推进指针容器可能会引起人们的兴趣,因为它们会为你完成所有艰苦的工作.

从阵列或容器中删除.

分配NULL不会导致容器/数组中的指针数量减少(它也不会处理delete),大小保持不变,但现在有指针无法合法取消引用.这使得代码的其余部分以extra if语句的形式变得更加复杂,并禁止以下内容:

// need to go out of our way to make sure there's no NULL here
std::for_each(v2.begin(),v2.end(), std::mem_fun(&foo::it));
Run Code Online (Sandbox Code Playgroud)

我真的不喜欢NULL在一般的指针序列中允许s 的想法,因为你很快就会把所有实际工作都埋没在一系列条件语句中.另std::vector一种erase方法是提供一个采用迭代器的方法,以便您可以编写:

v2.erase(v2.begin());
Run Code Online (Sandbox Code Playgroud)

删除第一个或v2.begin()+1第二个.std::vector由于时间的复杂性,没有简单的"擦除第n个元素"方法- 如果你正在进行大量的擦除,那么还有其他容器可能更合适.

对于阵列,您可以使用以下方法模拟擦除:

#include <utility>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
  int arr[] = {1,2,3,4};
  int len = sizeof(arr)/sizeof(*arr);
  std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // remove 2nd element, without preserving order:
  std::swap(arr[1], arr[len-1]);
  len -= 1;
  std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // and again, first element:
  std::swap(arr[0], arr[len-1]);
  len -= 1;
  std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

保留顺序需要一系列shuffle而不是单个swap,这很好地说明了擦除std::vector面的复杂性.当然,通过这样做,你只是重新创造了一个相当大的轮子,比标准的库容器免费为你做的更有用和灵活!

  • @ user695652如果要从容器中删除对象,则不需要数组. (2认同)