您应该为您的 B 类定义一个复制构造函数和一个赋值运算符。否则,您将遇到这些指针的严重问题。除此之外,第 1 行和第 3 行之间没有功能上的区别。唯一的区别在于实现。
话虽如此,没有理由在 B 中使用指针。如果您需要固定数量的整数,请使用纯整数或纯数组。如果您需要可变数量的整数,请使用std::vector
. 如果你真的需要分配动态内存,要非常小心并考虑使用智能指针。
如果您的 B 类仅包含一个 [pointer to] 整数,则可能类似于:
class B
{
private:
int * x;
public:
B (int i) { x = new int(i); }
B (const B & b) { x = new int(*b.x); }
~B() { delete x; }
B & operator= (const B & b) // Corner cases:
{ //
int * p = x; // 1) b and *this might
x = new int(*b.x); // be the same object
delete p; //
return *this; // 2) new might throw
} // an exception
};
即使在注释的极端情况下,此代码也会执行“正确的事情(TM)”。
另一种选择是:
#include <utility> // std::swap
class B
{
private:
int * x;
public:
B (int i) { x = new int(i); }
B (const B & b) { x = new int(*b.x); }
~B() { delete x; }
void swap (B & b)
{
using std::swap;
swap (x, b.x);
}
B & operator= (const B & b) // Corner cases:
{ //
B tmp(b); // 1) b and *this might
swap (tmp); // be the same object
return *this; //
} // 2) new might throw
}; // an exception
但是,如果有两个指针——就像在你的例子中——,你必须调用new
两次。如果第二个new
失败抛出异常,您会希望自动delete
保留第一个所保留的内存new
......
#include <utility> // std::swap
class B
{
private:
int * x;
int * y;
void init (int i, int j)
{
x = new int(i);
try
{
y = new int(j);
}
catch (...) // first new was OK but
{ // second failed, so undo
delete x; // first allocation and
throw; // continue the exception
}
}
public:
B (int i, int j) { init (i, j); }
B (const B & b) { init (*b.x, *b.y); }
~B() { delete x; delete y; }
void swap (B & b)
{
using std::swap;
swap (x, b.x);
swap (y, b.y);
}
B & operator= (const B & b) // Corner cases:
{ //
B tmp(b); // 1) b and *this might
swap (tmp); // be the same object
return *this; //
} // 2) new might throw
}; // an exception
如果你有三四个 [pointers to] int……代码会变得更加丑陋!这就是智能指针和 RAII(资源获取即初始化)真正有用的地方:
#include <utility> // std::swap
#include <memory> // std::unique_ptr (or std::auto_ptr)
class B
{
private:
std::auto_ptr<int> x; // If your compiler supports
std::auto_ptr<int> y; // C++11, use unique_ptr instead
public:
B (int i, int j) : x(new int(i)), // If 2nd new
y(new int(j)) {} // fails, 1st is
// undone
B (const B & b) : x(new int(*b.x)),
y(new int(*b.y)) {}
// No destructor is required
void swap (B & b)
{
using std::swap;
swap (x, b.x);
swap (y, b.y);
}
B & operator= (const B & b) // Corner cases:
{ //
B tmp(b); // 1) b and *this might
swap (tmp); // be the same object
return *this; //
} // 2) new might throw
}; // an exception