能否有人解释一下为什么指针不会初始化为NULL
?
例如:
void test(){
char *buf;
if (!buf)
// whatever
}
由于buf
不为null,程序不会进入if语句块。
我想知道,在什么情况下我们需要一个具有垃圾值的变量,特别是指向内存垃圾的指针?
能否有人解释一下为什么指针不会初始化为NULL
?
例如:
void test(){
char *buf;
if (!buf)
// whatever
}
由于buf
不为null,程序不会进入if语句块。
我想知道,在什么情况下我们需要一个具有垃圾值的变量,特别是指向内存垃圾的指针?
引用Bjarne Stroustrup在《C++程序设计语言》中的话(Special Edition p.22):
一个特性的实现不应该对不需要它的程序造成重大的负担。
D
所做的事情。如果您不想进行初始化,请使用以下语法:float f = void;
或 int* ptr = void;
。现在默认情况下已经初始化,但如果您真的需要,可以阻止编译器执行初始化。 - deft_code因为初始化需要时间。在C++中,你应该对任何变量的第一件事就是显式地进行初始化:
int * p = & some_int;
或者:
int * p = 0;
或者:
class A {
public:
A() : p( 0 ) {} // initialise via constructor
private:
int * p;
};
因为C++的座右铭之一是:
你不必支付你不使用的东西
正因为这个原因,vector
类的operator[]
方法不会检查索引是否越界。
出于历史原因,主要是因为这是在C语言中的做法。为什么在C语言中会这样做,另一个问题,但我认为“零开销原则”在这个设计决策中以某种方式起了作用。
极少数情况下,变量未初始化是有意义的,而默认初始化的成本很小,那么为什么要这样做呢?
C++不是C89。甚至C语言也不是C89。你可以混合声明和代码,所以应该推迟声明,直到有适当的值可以进行初始化。
指针只是另一种类型。如果您创建一个int
、char
或任何其他POD类型,它不会被初始化为零,那么为什么指针要被初始化为零呢?对于像这样编写程序的人来说,这可能被认为是不必要的开销。
char* pBuf;
if (condition)
{
pBuf = new char[50];
}
else
{
pBuf = m_myMember->buf();
}
如果您知道要初始化它,为什么程序在方法顶部首次创建pBuf
时应该产生成本?这就是零开销原则。
template<typename T> class InitializedPointer
{
public:
typedef T TObj;
typedef TObj *PObj;
protected:
PObj m_pPointer;
public:
// Constructors / Destructor
inline InitializedPointer() { m_pPointer=0; }
inline InitializedPointer(PObj InPointer) { m_pPointer = InPointer; }
inline InitializedPointer(const InitializedPointer& oCopy)
{ m_pPointer = oCopy.m_pPointer; }
inline ~InitializedPointer() { m_pPointer=0; }
inline PObj GetPointer() const { return (m_pPointer); }
inline void SetPointer(PObj InPtr) { m_pPointer = InPtr; }
// Operator Overloads
inline InitializedPointer& operator = (PObj InPtr)
{ SetPointer(InPtr); return(*this); }
inline InitializedPointer& operator = (const InitializedPointer& InPtr)
{ SetPointer(InPtr.m_pPointer); return(*this); }
inline PObj operator ->() const { return (m_pPointer); }
inline TObj &operator *() const { return (*m_pPointer); }
inline bool operator!=(PObj pOther) const
{ return(m_pPointer!=pOther); }
inline bool operator==(PObj pOther) const
{ return(m_pPointer==pOther); }
inline bool operator!=(const InitializedPointer& InPtr) const
{ return(m_pPointer!=InPtr.m_pPointer); }
inline bool operator==(const InitializedPointer& InPtr) const
{ return(m_pPointer==InPtr.m_pPointer); }
inline bool operator<=(PObj pOther) const
{ return(m_pPointer<=pOther); }
inline bool operator>=(PObj pOther) const
{ return(m_pPointer>=pOther); }
inline bool operator<=(const InitializedPointer& InPtr) const
{ return(m_pPointer<=InPtr.m_pPointer); }
inline bool operator>=(const InitializedPointer& InPtr) const
{ return(m_pPointer>=InPtr.m_pPointer); }
inline bool operator<(PObj pOther) const
{ return(m_pPointer<pOther); }
inline bool operator>(PObj pOther) const
{ return(m_pPointer>pOther); }
inline bool operator<(const InitializedPointer& InPtr) const
{ return(m_pPointer<InPtr.m_pPointer); }
inline bool operator>(const InitializedPointer& InPtr) const
{ return(m_pPointer>InPtr.m_pPointer); }
};
InitializedPointer<Foo> a
代替Foo *a
——这只是一种纯学术性的练习,因为Foo *a=0
更简洁。然而,从教育角度来看,上面的代码非常有用。通过对“占位”构造函数/析构函数和赋值操作进行一些修改,它可以轻松扩展到各种类型的智能指针,包括作用域指针(在析构函数中释放)和引用计数指针(通过在设置或清除m_pPointer时添加inc/dec操作)。 - Adisak请注意,静态数据将被初始化为0(除非您另有说明)。
是的,您应该尽可能晚地声明变量,并赋予一个初始值。像下面这样的代码
int j;
char *foo;
当您阅读到这段内容时,应该会引起警觉。我不知道是否有任何代码检查工具会对此发出警告,因为这是百分之百合法的。