C++ 指针在退出构造函数后更改值
出于某种原因,每当它将字符串重新指定为不同的const char*,它都会出错。在使用前一个缓冲区在字符串上创建新缓冲区后,当它存在于构造函数中时,缓冲区会无故更改值。我使用的是堆内存,所以它不应该受作用域的影响C++ 指针在退出构造函数后更改值,c++,string,C++,String,出于某种原因,每当它将字符串重新指定为不同的const char*,它都会出错。在使用前一个缓冲区在字符串上创建新缓冲区后,当它存在于构造函数中时,缓冲区会无故更改值。我使用的是堆内存,所以它不应该受作用域的影响 #include <iostream> class String { private: char* buffer; unsigned int size; public: String(const char* string) { si
#include <iostream>
class String {
private:
char* buffer;
unsigned int size;
public:
String(const char* string) {
size = strlen(string);
buffer = new char[size + 1];
memcpy(buffer, string, size + 1);
buffer[size] = 0;
}
String(const String& other) {
memcpy(this, new String(other.buffer), sizeof(String));
}
~String() {
delete buffer;
}
friend std::ostream& operator<<(std::ostream& stream, const String& str);
String operator+(const String& other) {
unsigned int nSize = this->size + other.size;
char* nBuffer = new char[nSize + 1];
memcpy(nBuffer, this->buffer, nSize + 1);
strcat(nBuffer, other.buffer);
nBuffer[nSize] = 0;
return String(nBuffer);
}
void operator+=(const String& other) {
unsigned int nSize = this->size + other.size;
char* nBuffer = new char[nSize + 1];
memcpy(nBuffer, this->buffer, nSize + 1);
strcat(nBuffer, other.buffer);
nBuffer[nSize] = 0;
this->~String();
memcpy(this, new String(nBuffer), sizeof(String));
}
};
std::ostream& operator<<(std::ostream& stream, const String& str) {
stream << str.buffer;
return stream;
}
int main() {
String test1 = "Hello";
test1 = "there";
std::cout << test1 << std::endl;
}
#包括
类字符串{
私人:
字符*缓冲区;
无符号整数大小;
公众:
字符串(常量字符*字符串){
大小=strlen(字符串);
缓冲区=新字符[大小+1];
memcpy(缓冲区、字符串、大小+1);
缓冲区[大小]=0;
}
字符串(常量字符串和其他){
memcpy(this,新字符串(other.buffer),sizeof(字符串));
}
~String(){
删除缓冲区;
}
friend std::ostream&Operator缓冲器,nSize+1);
strcat(nBuffer,其他缓冲区);
nBuffer[nSize]=0;
返回字符串(nBuffer);
}
void运算符+=(常量字符串和其他){
unsigned int nSize=this->size+other.size;
char*nBuffer=新字符[nSize+1];
memcpy(nBuffer,this->buffer,nSize+1);
strcat(nBuffer,其他缓冲区);
nBuffer[nSize]=0;
这个->~String();
memcpy(这个,新字符串(nBuffer),sizeof(字符串));
}
};
std::ostream&operatortest1=“there”
与test1=String(“there”)
相同,因为字符串“there”
必须转换为字符串。默认分配操作符通过将右侧的所有成员分配给左侧的成员来工作。它对所有成员进行浅层复制,因此字符串实际上不会重复,而是test1
中的buffer
指针和String(“there”)
都指向保存字符串的同一内存位置“there”
在赋值结束时,必须销毁字符串(“there”)
对象,因此它调用析构函数,该析构函数删除其缓冲区所指向的内存。在main()
方法的末尾,同样的情况也会发生在test1
中,只有当它到达那里时,才会发现内存已经被删除,从而导致运行时错误
当将原始指针作为类成员处理时,除了创建自己的复制构造函数外,还必须创建自己的复制赋值操作符来删除已保留的内存并分配新内存。一个简单的例子可能是这样的:
String& operator=(String const& other) {
delete[] buffer;
buffer = new char[other.size + 1];
strcpy(buffer, other.buffer);
size = other.size;
return *this;
}
现在分配到test1
将分配一个完全独立的内存空间来保存字符串。首先,复制构造函数是错误的。永远不要使用memcpy(这个
。它几乎总是错的。你那里有一个非常奇怪的复制构造函数。怎么会呢?我对这个低级编程非常陌生。你认为这个memcpy做什么?你的常规构造函数做一个新的
。你的常规析构函数做一个删除
。你只能删除新的
和exac所以,当复制的对象,复制构造的对象被销毁,它的析构函数被调用,它期望删除一些东西。那么,你能解释一下,在这个过程中,在哪一点,一些东西得到了新的,现在将被删除吗?我用手指数了数,一个新的,两个新的e> 删除
s。这对您有意义吗?分配操作符呢?您对此有何计划?除了我在回答中提到的主要问题外,您还有其他问题。即使用delete buffer
应该在哪里delete[]缓冲区
。太棒了。我甚至没意识到我可能会使赋值运算符过载。很有效!