如果以某种方式转换(数组指针,而不是内容),那么我会有问题。
是的,这正是发生的事情。
人们经常错误地认为数组只是指针。事情的真相是,每当你声明一个接受数组的函数时:
void foo(int x[10]);
声明被“调整”,因此参数是一个指针:
void foo(int *x); // C++ can't tell the difference between this and the first declaration
当您调用该函数时:
int x[10];
foo(x);
有一个等效于以下内容的隐式转换:
int x[10];
int *tmp = &x[0];
foo(tmp);
所以发生的事情是你有一块内存,其中包含指向长寿命对象的指针:
my_type *rest[count] = {new my_type, new my_type, new my_type};
您将指向该内存块的指针传递给线程:
thread(fnc, &rest[0], count);
然后当函数返回rest
超出范围时,该内存块不再有效。
然后线程跟随指向内存块的指针并读取垃圾。如果它确实读取了正确的数组内容,那么它可以很好地访问长寿命的对象。rest
问题是从曾经在堆栈上的损坏的内存块中获取指向长寿命对象的指针。
有没有办法抑制这种行为?
在大多数情况下,唯一有意义的就是不使用原始数组作为函数参数。您可以将原始数组包装在结构中并获得合理的行为:
struct int_array {
int x[10];
};
void foo(int_array x);
int main() {
int_array x = {1,2,3,4,5,6,7,8,9,0};
foo(x); // the array is copied rather than getting strangely converted
}
这几乎就是std::array
它的作用,所以你最好使用它。
如果您不想要数组的副本,您可以引用该数组:
int foo(int (&x)[10]);
这为您提供了与在您背后使用int foo(int x[10]); foo(x);
. 这里的好处是它是明确的,并且您可以对数组的大小进行类型检查。也就是说,由于“调整”,以下不会导致编译器错误:
int foo(int x[10]);
int x[3];
foo(x);
而这将:
int foo(int (&x)[10]);
int x[3];
foo(x); // the implicit conversion to &x[0] does not get happen when the function takes a reference to array