2013-06-06 86 views
0
#include <cstdlib> 
#include <cstring> 
#include <string> 

using std::string; 

string *arr_ptr; 
int capacity; 

void add() { 
    int old_capacity = capacity; 
    capacity <<= 1; 
    // double the capacity 
    string *tmp_ptr = new string[capacity]; 
    // apply new space 
    memmove(tmp_ptr, arr_ptr, sizeof(string) * old_capacity); 
    // copy 
    delete[] arr_ptr; 
    // free the original space 
    arr_ptr = tmp_ptr; 

    arr_ptr[capacity - 1] = "occupied"; 
    // without this statement, everything "seems" to be fine. 
} 

int main() { 
    arr_ptr = new string[1]; 
    capacity = 1; 
    for (int i = 0; i < 3; i++) add(); 
} 

运行代码。正如你所看到的,当字符串的desctrutor被调用时,程序崩溃。尝试对delete的行进行注释并再次检查。为什么我不能std :: string?

我怀疑std :: string会保留自己的一些地址信息。它在内存中的位置发生变化时不会被通知。

此外,由于memmove并不总是按预期工作,在C++中复制类实例数组的适当表达式是什么?

+4

使用'std :: vector'。 – chris

+0

必须第二克里斯。不要将旧式风格的数组与老式风格的“新”(好的)stl容器/类混合使用。 – Najzero

+0

@chris我正在为我的数据结构类写作业。 XD – Determinant

回答

1

memmove是复制字节的低级功能。这意味着一个字节数组的值被复制到另一个数组中。这对于POD数据很好,但不适用于其他任何内容。原因是类可以有一个拷贝构造函数,这个拷贝构造函数不会被memmove调用,并且类可以拥有额外的数据,比如用于调用虚拟成员函数的vpointer。

你最简单的解决办法是更换memmovestd::copy为(#include <algorithm>)的副本条目,而不是字节:

std::copy(arr_ptr, arr_ptr + old_capacity, tmp_ptr); 
0

1日你不初始化容量值作为:

int capacity; 

应该是:

int capacity = 0; 

,当你尝试这样操作:

arr_ptr[capacity - 1] = "occupied"; 

有是可能发生的引用错误。

0

该程序的行为是::std::string执行相关。

如果字符串的实现使用堆内存来存储字符,则字符串的一个实例意味着有两个指针指向相同的堆内存。调用其中一个字符串实例的析构函数会导致释放堆内存,导致另一个字符串实例具有悬挂指针。

所以不要memmove串:)

+0

你能详细解释一下:“移动一个字符串的实例意味着有两个指向同一个堆内存的指针”? – Determinant

1

我相信你在找什么是string::reserve

在你的代码中,你也试图创建一个字符串数组(而不是字符串数组)。

你在这里做的是复制对象的'字符串',而不是它的内容(因为你不调用它的构造函数/析构函数)。 因此,当你'删除'你的“arr_ptr”时,析构函数释放相关的数据。 当您尝试使用tmp_ptr访问它时,程序段错误。

+0

+1“复制对象'字符串',而不是其内容” – Determinant

相关问题