检查 char 指针是否为空 - 复制构造函数
Checking to see if a char pointer is null - Copy Constructor
我正在编写以下代码
class base
{
private:
char* mycharpointer;
std::string mystring;
public:
base() : mycharpointer(NULL) {/*default constructor*/}
//Copy Constructor
base(const base& rhs){
if(mycharpointer != NULL) ---> Why is this condition true ?
{
mycharpointer = new char[ strlen(rhs.mycharpointer + 1)];
strcpy(this->mycharpointer,rhs.mycharpointer);
}
mystring = rhs.mystring;
}
base operator=(base& b)
{
if(this == &b)
return *this;
base temp(b);
temp.swap(*this);
return *this;
}
//Swap operation
void swap(base& lhs) {
std::swap(lhs.mycharpointer,this->mycharpointer);
std::swap(lhs.mystring,this->mystring);
}
//Destructor
virtual ~base(){
if(mycharpointer)
delete[] mycharpointer;
}
};
class der : public base
{
public:
char* mycharpointer_der;
std::string mystring_der;
foo* f;
public:
der():mycharpointer_der(NULL)
{
}
der(const der& rhs) : base(rhs)
{
if(mycharpointer_der)
{
mycharpointer_der = new char[ strlen(rhs.mycharpointer_der + 1)];
strcpy(this->mycharpointer_der,rhs.mycharpointer_der);
}
mystring_der = rhs.mystring_der;
f = new foo(*rhs.f);
}
der& operator=(der& d)
{
if(this == &d) //Make sure its not the same class
return *this;
base::operator= (d);
der temp(d);
temp.swap(*this);
return *this;
}
//Swap operation
void swap(der& lhs) {
std::swap(lhs.mycharpointer_der,this->mycharpointer_der);
std::swap(lhs.mystring_der,this->mystring_der);
}
virtual ~der(){
if(mycharpointer_der) //Necessary check as to make sure you are not deleting a NULL address otherwise exception thrown.
delete[] mycharpointer_der;
}
};
int main()
{
der d;
d.mycharpointer_der = "Hello World";
d.mystring_der = "Hello String";
der b;
b = d;
}
现在在上面的代码中调用了 d 的复制赋值运算符。在 return 中调用基 class 的复制赋值运算符。在基 class 的复制赋值运算符中,基 class 的复制构造函数被调用。我的问题是为什么条件
if(mycharpointer != NULL)
在基地 class 结果是真的?即使我在基 class.
的初始化列表中明确地为它分配了一个 NULL
那张支票太荒谬了。在构造点,当我们进入主体时,mycharpointer
是默认初始化的并且将包含一些垃圾值, 可能 是 0
但可能不会'不是。
也就是说,如果 rhs.mycharpointer
为 NULL 会怎样?那么 strlen
调用就会失败。这是您需要检查其值的 charpointer
:
base(const base& rhs)
{
if (rhs.mycharpointer) {
mycharpointer = new char[ strlen(rhs.mycharpointer) + 1 ];
// outside the parens ^^^^
strcpy(this->mycharpointer,rhs.mycharpointer);
}
else {
mycharpointer = NULL;
}
mystring = rhs.mystring;
}
或者因为您已经在使用 string
,我们也可以继续使用 string
来实现 mycharpointer
。这有一个额外的好处,我们甚至不必编写复制构造函数,如您所见,它很容易出错:
base(const base& ) = default;
C++编译器只确保全局变量和静态变量被初始化,所以在这种情况下,mycharpointer实际上可能指向一些无用的垃圾(悬空指针)
base(const base& rhs){
if(mycharpointer != NULL) ---> Why is this condition true ?
{
mycharpointer = new char[ strlen(rhs.mycharpointer + 1)];
strcpy(this->mycharpointer,rhs.mycharpointer);
}
mystring = rhs.mystring;
}
因为mycharpointer实际指向的是堆上分配的数据,所以如果要重定位,需要先释放已有的数据。
类似于:
if ( mycharpointer) {
delete [] mycharpointer;
}
显然您希望默认构造函数在复制构造函数之前 运行。
但不会。
我正在编写以下代码
class base
{
private:
char* mycharpointer;
std::string mystring;
public:
base() : mycharpointer(NULL) {/*default constructor*/}
//Copy Constructor
base(const base& rhs){
if(mycharpointer != NULL) ---> Why is this condition true ?
{
mycharpointer = new char[ strlen(rhs.mycharpointer + 1)];
strcpy(this->mycharpointer,rhs.mycharpointer);
}
mystring = rhs.mystring;
}
base operator=(base& b)
{
if(this == &b)
return *this;
base temp(b);
temp.swap(*this);
return *this;
}
//Swap operation
void swap(base& lhs) {
std::swap(lhs.mycharpointer,this->mycharpointer);
std::swap(lhs.mystring,this->mystring);
}
//Destructor
virtual ~base(){
if(mycharpointer)
delete[] mycharpointer;
}
};
class der : public base
{
public:
char* mycharpointer_der;
std::string mystring_der;
foo* f;
public:
der():mycharpointer_der(NULL)
{
}
der(const der& rhs) : base(rhs)
{
if(mycharpointer_der)
{
mycharpointer_der = new char[ strlen(rhs.mycharpointer_der + 1)];
strcpy(this->mycharpointer_der,rhs.mycharpointer_der);
}
mystring_der = rhs.mystring_der;
f = new foo(*rhs.f);
}
der& operator=(der& d)
{
if(this == &d) //Make sure its not the same class
return *this;
base::operator= (d);
der temp(d);
temp.swap(*this);
return *this;
}
//Swap operation
void swap(der& lhs) {
std::swap(lhs.mycharpointer_der,this->mycharpointer_der);
std::swap(lhs.mystring_der,this->mystring_der);
}
virtual ~der(){
if(mycharpointer_der) //Necessary check as to make sure you are not deleting a NULL address otherwise exception thrown.
delete[] mycharpointer_der;
}
};
int main()
{
der d;
d.mycharpointer_der = "Hello World";
d.mystring_der = "Hello String";
der b;
b = d;
}
现在在上面的代码中调用了 d 的复制赋值运算符。在 return 中调用基 class 的复制赋值运算符。在基 class 的复制赋值运算符中,基 class 的复制构造函数被调用。我的问题是为什么条件
if(mycharpointer != NULL)
在基地 class 结果是真的?即使我在基 class.
的初始化列表中明确地为它分配了一个 NULL那张支票太荒谬了。在构造点,当我们进入主体时,mycharpointer
是默认初始化的并且将包含一些垃圾值, 可能 是 0
但可能不会'不是。
也就是说,如果 rhs.mycharpointer
为 NULL 会怎样?那么 strlen
调用就会失败。这是您需要检查其值的 charpointer
:
base(const base& rhs)
{
if (rhs.mycharpointer) {
mycharpointer = new char[ strlen(rhs.mycharpointer) + 1 ];
// outside the parens ^^^^
strcpy(this->mycharpointer,rhs.mycharpointer);
}
else {
mycharpointer = NULL;
}
mystring = rhs.mystring;
}
或者因为您已经在使用 string
,我们也可以继续使用 string
来实现 mycharpointer
。这有一个额外的好处,我们甚至不必编写复制构造函数,如您所见,它很容易出错:
base(const base& ) = default;
C++编译器只确保全局变量和静态变量被初始化,所以在这种情况下,mycharpointer实际上可能指向一些无用的垃圾(悬空指针)
base(const base& rhs){
if(mycharpointer != NULL) ---> Why is this condition true ?
{
mycharpointer = new char[ strlen(rhs.mycharpointer + 1)];
strcpy(this->mycharpointer,rhs.mycharpointer);
}
mystring = rhs.mystring;
}
因为mycharpointer实际指向的是堆上分配的数据,所以如果要重定位,需要先释放已有的数据。 类似于:
if ( mycharpointer) {
delete [] mycharpointer;
}
显然您希望默认构造函数在复制构造函数之前 运行。
但不会。