【发布时间】:2018-11-07 22:21:43
【问题描述】:
首先我有三个文件,
mystring.cpp 用于实现功能。
#include <iostream>
#include "mystring.hpp"
// Default constructor
MyString::MyString()
{
data = 0;
length = 0;
}
MyString::MyString(int n)
{
data = new char [n];
length = n;
}
MyString::MyString(const char* str, int n)
{
length = n;
data = new char [n];
for (int i = 0; i < n; i++)
{
data[i] = str[i];
}
}
void MyString::trim(int n)
{
if(n < length)
{
int newlength = n;
char* newdata = new char [newlength];
for (int i = 0; i < newlength; i++)
{
newdata[i] = data[i];
}
delete[] data;
data = newdata;
length = newlength;
}
}
MyString::~MyString()
{
delete[] data;
}
void MyString::append(const MyString& rhs)
{
// Determine the length of the resulting
// string and allocate room for it.
int newlength = length + rhs.length;
char* newdata = new char [newlength];
// Copy the current string's data
for (int i = 0; i < length; i++)
{
newdata[i] = data[i];
}
// Copy the given string's data
for (int i = 0; i < rhs.length; i++)
{
newdata[i + length] = rhs.data[i];
}
// Now we must deallocate the original memory
// and update the member variables
delete[] data;
data = newdata;
length = newlength;
}
void MyString::print(char separator) const
{
for (int i = 0; i < length - 1; i++)
{
std::cout << data[i] << separator;
}
std::cout << data[length - 1] << std::endl;
}
其次是一个头文件 mystring.hpp
#ifndef __mystring_hpp__
#define __mystring_hpp__
class MyString
{
public:
// Constructors
MyString();
MyString(int n);
MyString(const char* str, int n);
~MyString();
// Modify the current string by appending "rhs" to it
void append(const MyString& rhs);
// Trim the string such that it contains "n" characters.
// If "n" is larger than the current string's length,
// then do nothing.
void trim(int n);
// Prints this string by putting the separator
// character between each element in the data.
// By default, do not print anything.
void print(char separator = '\0') const;
// This is the destructor. It is automatically
// called when an object of this class is destroyed.
//~MyString(); //Implement!
// This is the assignment operator which is automatically
// called when an object of type MyString is assigned
// to another object of the same type. Technically, it
// does not have to return "MyString&" but we do so to
// allow chaining assignments such as: str1 = str2 = str3
//MyString& operator=(const MyString& rhs); //Implement!
// Copy constructor. Different from the assignment operator,
// this is called when an object is "being created" as a
// copy of another object.
//MyString(const MyString& rhs); //Implement!
private:
char* data;
int length;
};
#endif // __mystring_v1_hpp__
最后是包含 main.cpp 的 main_assignment.cpp
#include "mystring.hpp"
int main()
{
MyString str1("ali", 3);
MyString str2("veli", 4);
str1 = str2;
return 0;
}
这里的问题是,我没有为 MyString 类重载赋值运算符,所以在 *main_assignment.cpp * 中,两个字符串应该指向同一个内存,当程序返回时,它应该首先尝试释放两个字符串中的一个但是当涉及到另一个时,它会尝试释放一个指向一些“未定义”内存的指针。
在我看来,它应该崩溃但程序运行完美,为什么?
【问题讨论】:
-
因为它被命名为undefined行为是有原因的。
-
__mystring_hpp__-- 不要使用前导双下划线作为标识符。带有前导双下划线的标识符保留给编译器实现。 -
离题,但有一些建议——您的
trim函数只需要更改length。真的不需要重新分配和复制相同的数据——让length控制字符串实际具有的字符数。 -
@user9679818:您要为哪个操作系统、哪个编译器、哪个构建模式和哪个平台编译?我复制/粘贴了您在 VS2017 中编译的代码,它在调试和发布版本 x86 中都崩溃了。
-
@trim 感谢您的建议 :)
标签: c++ class pointers memory-management