【问题标题】:Creating unknown number of objects with each having specific object name at runtime c++在运行时创建未知数量的对象,每个对象都具有特定的对象名称 c++
【发布时间】:2014-02-11 14:46:56
【问题描述】:

我想在运行时在主方法中创建未知数量的对象,每个对象都有一个特定的对象名称。对象应该存在直到程序结束(主方法结束)。请注意,在我的例子中,对象是字段。

我想过这样的解决方案:

for ( i=1 ; i <= NumberOfObjects ; i++)
{

if (i==1)
{
MyClass *ObjectName1 = new MyClass();

}

if (i==2)
{
MyClass *ObjectName2 = new MyClass();

}

.   //more if statements for more objects
.
.

} //for loop closed

问题:

  1. 我不认为这个解决方案很好,因为创建的对象的数量仍然会限制在 for 循环中的 if 语句中。有更好的解决方案吗?

  2. 循环中指针的范围:退出 if 块时,指针超出范围。之后如何访问带有“新”创建的对象?

【问题讨论】:

  • 你能详细说明你为什么要这样做吗?几乎可以肯定有更好的方法。
  • 只需使用 std::map 并使用生成的密钥存储每个新对象,该密钥将“命名”它。
  • 无意冒犯,但我很想对这个问题投赞成票,因为它是惊人的新手:-D
  • 你不能,在c++中编译后的对象没有名字
  • @JBentley:需要创建的对象(字段)的数量是从文件中读取的,这个数量由程序用户决定......

标签: c++ loops scope object-lifetime


【解决方案1】:

命名变量在代码编译后被删除,之后对您没有任何意义。

看起来你需要一个查找表,使用带有字符串键的 std::map 或 std::unordered_map 作为对象的名称。

std::map<std::string, MyClass*> variablesTable;
for ( i=1 ; i <= NumberOfObjects ; i++)
{
    std::ostringstream oss << "name" << i;
    variablesTable[oss.str()] = new MyClass();    //you actually need to check if it exists, otherwise will be overwritten.
}    

如果您希望每个创建的对象都为每个对象运行单独的代码,您可以拥有一个函数对象表(或将两者都存储在一个元组中),例如 std::map&lt;std::string, std::&lt;MyClass, Func&gt;&gt;.

如果你想查找就使用,

MyClass* object = variablesTable[strName];
object->CallFunction();

附: hash_maps 的一个已知技巧是在构建项目之前运行脚本以将任何文字字符串转换为 int,因为比较 int 比字符串快。至少我知道这曾在 Uncharted 系列中使用过(但与您的情况几乎不相关)。

【讨论】:

  • 你能告诉我“auto”到底是什么吗?据我了解,您正在创建类型为“auto”的指针“object”,它指向名为“strName”的地图元素,然后在对象上使用方法“CallFunction()”。我不明白这个:)
  • @Sreight 我刚改了。 auto 是 C++11 中的一个新关键字,它可以推断类型。如果您使用的是不支持 C++11 的编译器,则不能使用 auto。只需将 auto 替换为从表达式右侧返回的类型
【解决方案2】:

要详细说明您的方法,不需要循环。您可以将其简化为

MyClass *ObjectName1 = new MyClass();
MyClass *ObjectName2 = new MyClass();
MyClass *ObjectName3 = new MyClass();
...

当您离开if 语句时,指针的范围和生命周期已经结束。要访问 if/for 语句之外的指针,您必须将它们移到循环之前。

我只会使用 std::vector 的对象

std::vector<MyClass*> objects;
for (int i = 1; i <= NumberOfObjects; i++) {
    MyClass *p = new MyClass();
    objects.push_back(p);
}

这不会为每个对象提供一个单独的名称,但至少是可维护的。

更新:

为了解决内存泄漏的问题,你也可以直接在vector中创建对象,不需要显式的new

std::vector<MyClass> objects;
for (int i = 1; i <= NumberOfObjects; i++)
    objects.push_back(MyClass());

这将为您提供对象,并在矢量范围结束时自动清理它们。

【讨论】:

  • 虽然这可能是解决他的问题的更好方法,但它实际上并不能回答问题,应该是评论。
  • 另外,没有循环或if 语句的版本不允许在运行时决定对象的数量
  • 应该将 p 创建为指针吗? objects.push_back(p) 将失败。此外,你可以在 for 循环中执行 MyClass p before 并在其中设置 p=MyClass(),这样您就不会在每次迭代中创建一个新的 p。
  • @OlafDietsche 您正在更新对象 (new MyClass()),但它们从未清理过。
  • 你为什么要切换到存储指针向量,这需要手动清理,而不是仅仅创建对象并将其正确存储为值,然后让向量析构函数为你清理它们?
【解决方案3】:

您将需要一些东西来存储这些对象。例如,您可以使用std::vectorstd::map。您可以在这些数据结构中存储无限数量的对象(实际上您受到内存量的限制,比如说几乎无限),而无需关心内存,因为它是自动管理的。

【讨论】:

  • 我投反对票的原因:(1)std::vector 不允许 OP 命名他的对象,(2)std::map 将但需要更多的工作才能提出名称,而且您还没有解释 OP 应该如何使用它,(3) 关于无限制/几乎无限制的评论是不恰当的,因为我们不知道 OP 正在使用什么内存限制或他的对象有多大。
  • 我会去找我的鞭笞工具。
  • @JBentley:命名要求不明确:OP 使用 ObjectName1ObjectName[0] 似乎等价。
  • @jarod42 我不认为这不清楚。我同意 OP 可能应该使用ObjectName[0] 之类的东西,但他目前所说的问题要求单个命名对象。
【解决方案4】:

编辑:好的,这不是答案。 OP 想要在运行时进行任意对象计数! 这个问题可能是一个模板元编程问题。

使用向量存储指针,使用宏定义新指针并将其压入向量。 结束前,使用矢量释放。

#include <vector>

#define DEFVAR( varname )      \
    foo* varname = new foo();  \
    v.push_back( varname )

class foo {};

int main() {

   std::vector<foo*> v;

   DEFVAR( ObjName1 );
   DEFVAR( ObjName2 );
   DEFVAR( ObjName3 );
   DEFVAR( ObjName4 );

   [ .... ]

   for ( size_t index = 0; index < v.size(); ++index ) delete v[ index ];

   return 0;

}

【讨论】:

  • 如果您要硬编码对象的数量及其名称,为什么不直接在代码中进行呢?我看不出宏在这里有什么用途,或者它如何解决 OP 的问题。
  • @JBentley 我只是想将一个简单的定义/命名指令与末尾的“一行”删除结合起来。
猜你喜欢
  • 1970-01-01
  • 2014-11-27
  • 1970-01-01
  • 2018-04-13
  • 2014-09-23
  • 2013-04-05
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多