我不是一个非常有经验的c ++编码器,这让我很难过。我将一个对象(在别处创建)传递给一个函数,我希望能够将该对象存储在某个数组中,然后运行该数组来调用该对象上的函数。这是一些伪代码:
void AddObject(T& object) {
object.action(); // this works
T* objectList = NULL;
// T gets allocated (not shown here) ...
T[0] = object;
T[0].action(); // this doesn't work
}
我知道对象正确传递,因为第一次调用object.action()
会做到它应该做的事情。但是当我将对象存储在数组中时,尝试调用action()
会导致严重崩溃。
可能我的问题是我只是修改了。和*,直到编译完成,T[0].action()
编译但在运行时崩溃。
答案 0 :(得分:1)
您问题的最简单答案是,您必须正确声明容器和,您必须为您的班级定义适当的分配运算符。尽可能密切地与您的示例一起工作:
typedef class MyActionableClass T;
T* getGlobalPointer();
void AddInstance(T const& objInstance)
{
T* arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing
//**copy** the instance we've received
arrayFromElsewhere[0] = objInstance;
//now invoke the action() method on our **copy**
arrayFromElsewhere[0].action();
}
请注意 const reference 的签名更改,强调我们将复制原始对象,而不是以任何方式更改它。
同样请注意:arrayFromElsewhere [0] .action()与
虽然很明显你已经凝聚了,但凝结使得这样做的原因不太明显 - 例如,指定你想维护一个回调对象数组会为“需要”这个功能提供更好的理由。像你一样使用“T”也是一个糟糕的选择,因为这往往意味着模板使用给大多数有经验的C ++程序员。
最有可能导致“无法解释”崩溃的事情是任务操作员;如果你没有定义一个,编译器会自动生成一个作为按位复制的文件 - 几乎可以肯定不你想要的东西,如果你的类不是简单数据类型(POD)的集合。
为了在任何复杂的类上正常工作,您可能需要定义深层副本或使用引用计数;在C ++中,让编译器为你创建任何ctor,dtor或赋值几乎总是一个糟糕的选择。
当然,使用标准容器而不是您的示例所暗示的简单数组机制是个好主意。在这种情况下,由于容器和算法的假设,您可能还应该定义默认的ctor,虚拟dtor和copy ctor。
事实上,如果不想要创建对象的副本,而是希望在原始对象上调用action()一个数组,那么你需要一个指针数组。再次与原始示例密切合作:
typedef class MyActionableClass T;
T** getGlobalPointer();
void AddInstance(T& objInstance)
{
T** arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing
//**reference** the instance we've received by saving its address
arrayFromElsewhere[0] = &objInstance;
//now invoke the action() method on **the original instance**
arrayFromElsewhere[0]->action();
}
请注意,arrayFromElsewhere现在是一个指向对象的指针的数组,而不是实际对象的数组。
请注意,我在这种情况下删除了const修饰符,因为我不知道action()是否是一个const方法 - 具有类似我假设的名称...
请仔细注意分配中使用的&符号(地址)运算符。
还要注意使用指针运算符调用action()方法的新语法。
最后要注意的是,使用标准的指针容器充满了内存泄漏危险,但通常几乎与使用裸阵列一样危险: - /
答案 1 :(得分:0)
我很惊讶它编译。您声明了一个指向objectList
的8个指针的T
数组。然后指定T[0] = object;
。这不是你想要的,你想要的是
T objectList[8];
objectList[0] = object;
objectList[0].action();
或
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
现在我正在等待C ++专家解释你的代码编译的原因,我真的很好奇。
答案 2 :(得分:0)
您可以将对象放入动态或静态数组中:
#include <vector> // dynamic
#include <array> // static
void AddObject(T const & t)
{
std::array<T, 12> arr;
std::vector<T> v;
arr[0] = t;
v.push_back(t);
arr[0].action();
v[0].action();
}
但这并没有多大意义;你通常会在函数之外的其他地方定义你的数组。