我知道这可能听起来很奇怪,但是,这是2009年,我需要使用BCB5编写小应用程序:)
问题是当尝试从工作线程中扩展它时,DynamicArray会抛出OutOfBound异常。
我有全局变量,比方说
DynamicArray<double> X;
在主线程中我检查数组的长度,我得到0,这是OK(长度未设置)
Application->MessageBox(itoa(X.Length,str , 10), "", MB_OK);
以下是我的工作线程类
class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;
protected:
void __fastcall Execute();
public:
__fastcall ArrayModifierThread(bool CreateSuspended);
void setX(DynamicArray<double> &a);
};
到目前为止一切顺利。接下来我创建新线程:
ArrayModifierThread *t = new ArrayModifierThread(true);
t->setX(X); // Pass reference to my global DynamicArray
t->Resume();
这里执行Execute()方法:
void __fastcall ArrayModifierThread::Execute()
{
X.Length = 10;
X[5] = 45.5;
}
我期望的是全局数组被扩展,第6个元素的值达到45.5。
但是从主线程中进行更仔细的调查会得到Length = 0和ArrayOfBounds Exception:
Application->MessageBox(itoa(__X.Length,str , 10), "", MB_OK);
Application->MessageBox(itoa(__X[5],str , 10), "", MB_OK);
有人能告诉我我错过了什么吗?
答案 0 :(得分:1)
在Execute
方法中,您正在修改主题的 X
字段,而不是全局X
变量。虽然setX
方法通过引用接收其参数,但成员变量不是引用。它存储DynamicArray
值的副本,更改Length
属性可确保它引用唯一数组。
setX
函数接收对全局变量的引用,正如您在“回答”中正确观察到的那样,但它保持参考它。它在分配对象的X
字段时会复制它。
也许您打算将X
声明为参考:
private:
DynamicArray<double>& X;
这可行。您的setX
函数将不再起作用,因为在初始化之后您不允许“重新定位”引用。相反,您需要在线程的构造函数中初始化它:
ArrayModifierThread(DynamicArray<double>& a): X(a) { ... }
您还可以将指针存储到数组而不是引用:
private:
DynamicArray<double>* X;
public:
void setX(DynamicArray<double>& a) {
X = &a;
}
protected:
void Execute() {
X->Length = 10;
(*X)[5] = 45.5;
}
您需要注意的是,您的代码不是线程安全的。 (这里也不是我的。)你有多个线程修改相同的共享资源(数组)而没有任何保护,例如关键部分。但这超出了这个问题的范围。首先搜索Stack Overflow和Web的其余部分,如果您需要有关该问题的帮助,请回来询问新问题。
答案 1 :(得分:1)
它不起作用,因为成员X不是参考。当您调用set()时,您正在创建该对象的本地副本,然后Execute()正在修改本地版本。
class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;
void __fastcall ArrayModifierThread::Execute()
{
X.Length = 10;
X[5] = 45.5;
}
有三种替代解决方案:
将您的本地成员变量X作为参考 由于必须在构造时初始化引用,因此不能使用set()来修改它,因此将引用传递给对象的构造函数并将其保存在那里。
使本地成员变量X成为指针。 使用set()时,请获取传入参数的地址(注意它是一个引用,因此您将获得它引用的对象的地址)。这也意味着需要修改执行以考虑X是一个指针。
不要使用本地成员变量。只需直接修改全局。
答案 2 :(得分:0)
嗯,这对我来说不太清楚。 我想因为void setX(DynamicArray&amp; a),工作线程获得对全局变量的引用。
您可以发布示例代码应该如何完成?
这就是我的void setX(DynamicArray&amp; a)的样子:
void ArrayModifierThread::setX(DynamicArray<double> &a)
{
X = a;
}