C++ 为什么默认情况下不使用 NULL 初始化指针?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1910832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:34:40  来源:igfitidea点击:

Why aren't pointers initialized with NULL by default?

c++memorypointersinitialization

提问by Jonathan

Can someone please explain why pointers aren't initialized to NULL?
Example:

有人可以解释为什么指针没有初始化为NULL
例子:

  void test(){
     char *buf;
     if (!buf)
        // whatever
  }

The program wouldn't step inside the if because bufis not null.

程序不会进入 if 因为buf不为空。

I would like to know why, in what case do we need a variable with trash on, specially pointers addressing the trash on the memory?

我想知道为什么,在什么情况下我们需要一个带垃圾的变量,特别是指向内存垃圾的指针?

回答by Martin York

We all realize that pointer (and other POD types) should be initialized.
The question then becomes 'who should initialize them'.

我们都意识到应该初始化指针(和其他 POD 类型)。
那么问题就变成了“谁应该初始化它们”。

Well there are basically two methods:

那么基本上有两种方法:

  • The compiler initializes them.
  • The developer initializes them.
  • 编译器初始化它们。
  • 开发人员初始化它们。

Let us assume that the compiler initialized any variable not explicitly initialized by the developer. Then we run into situations where initializing the variable was non trivial and the reason the developer did not do it at the declaration point was he/she needed to perform some operation and then assign.

让我们假设编译器初始化了开发人员未明确初始化的任何变量。然后我们遇到了初始化变量不是微不足道的情况,开发人员没有在声明点这样做的原因是他/她需要执行一些操作然后分配。

So now we have the situation that the compiler has added an extra instruction to the code that initializes the variable to NULL then later the developer code is added to do the correct initialization. Or under other conditions the variable is potentially never used. A lot of C++ developers would scream foul under both conditions at the cost of that extra instruction.

所以现在我们的情况是,编译器在代码中添加了一条额外的指令,将变量初始化为 NULL,然后添加开发人员代码以进行正确的初始化。或者在其他条件下,变量可能永远不会被使用。许多 C++ 开发人员会以额外指令为代价在这两种情况下尖叫。

It's not just about time. But also space. There are a lot of environments where both resources are at a premium and the developers do not want to give up either.

这不仅仅是时间问题。但也有空间。在很多环境中,这两种资源都非常宝贵,开发人员也不想放弃。

BUT: You can simulate the effect of forcing initialization. Most compilers will warn you about uninitialized variables. So I always turn my warning level to the highest level possible. Then tell the compiler to treat all warnings as errors. Under these conditions most compilers will then generate an error for variables that are un-initialized but used and thus will prevent code from being generated.

但是:您可以模拟强制初始化的效果。大多数编译器会警告您未初始化的变量。所以我总是把我的警告级别调到可能的最高级别。然后告诉编译器将所有警告视为错误。在这些情况下,大多数编译器将为未初始化但已使用的变量生成错误,从而阻止生成代码。

回答by John

Quoting Bjarne Stroustrup in TC++PL (Special Edition p.22):

在 TC++PL(特别版第 22 页)中引用 Bjarne Stroustrup:

A feature's implementation should not impose significant overheads on programs that do not require it.

一个特性的实现不应该给不需要它的程序带来很大的开销。

回答by John

Because initialisation takes time. And in C++, the very first thing you should do with any variable is to explicitly initialise it:

因为初始化需要时间。在 C++ 中,你应该对任何变量做的第一件事是显式初始化它:

int * p = & some_int;

or:

或者:

int * p = 0;

or:

或者:

class A {
   public:
     A() : p( 0 ) {}  // initialise via constructor
   private:
     int * p;
};

回答by KeatsPeeks

Because one of the mottos of C++ is :

因为 C++ 的座右铭之一是:



You don't pay for what you don't use

你不会为你不使用的东西付费



For this very reason, the operator[]of the vectorclass does not check if the index is out of bounds, for instance.

正是出于这个原因,例如operator[]vector类的 不检查索引是否越界。

回答by AraK

For historical reasons, mainly because this is how it is done in C. Why it is done like that in C, is another question, but I think that the zero overhead principlewas involved somehow in this design decision.

由于历史原因,主要是因为在 C 中是这样完成的。为什么在 C 中这样做是另一个问题,但我认为零开销原则以某种方式参与了这个设计决策。

回答by Joshua

Besides, we do have a warning for when you blow it: "is possibly used before assigned a value" or similar verbage depending on your compiler.

此外,我们确实有一个警告,当你吹它时:“可能在分配值之前使用”或类似的措辞,具体取决于您的编译器。

You do compile with warnings, right?

你编译时有警告,对吧?

回答by DrPizza

There are vanishingly few situations in which it ever makes sense for a variable to be uninitialized, and default-initialization has a small cost, so why do it?

在极少数情况下,变量未初始化是有意义的,并且默认初始化的成本很小,那么为什么要这样做呢?

C++ is not C89. Hell, even C isn't C89. You can mix declarations and code, so you should defer declaration until such a time as you have a suitable value to initialize with.

C++ 不是 C89。见鬼,即使是 C 也不是 C89。你可以混合声明和代码,所以你应该推迟声明,直到你有一个合适的值来初始化。

回答by LeopardSkinPillBoxHat

A pointer is just another type. If you create an int, charor any other POD type it isn't initialised to zero, so why should a pointer? This could be considered unnecessary overhead to someone who writes a program like this.

指针只是另一种类型。如果你创建一个intchar或任何其他类型的POD它不初始化为零,所以为什么要一个指针?对于编写这样的程序的人来说,这可能被认为是不必要的开销。

char* pBuf;
if (condition)
{
    pBuf = new char[50];
}
else
{
    pBuf = m_myMember->buf();
}

If you know you're going to initialise it, why should the program incur a cost when you first create pBufat the top of the method? This is the zero overhead principle.

如果您知道要初始化它,为什么在您第一次pBuf在方法顶部创建程序时会产生成本?这就是零开销原则。

回答by Adisak

If you want a pointer that is always initialized to NULL, you can use a C++ template to emulate that functionality:

如果您想要一个始终初始化为 NULL 的指针,您可以使用 C++ 模板来模拟该功能:

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); }
};

回答by pm100

Note that static data is initialized to 0 (unless you say otherwise).

请注意,静态数据初始化为 0(除非您另有说明)。

And yes, you should always declare your variables as late as possible and with an initial value. Code like

是的,您应该始终尽可能晚地声明变量并使用初始值。代码如

int j;
char *foo;

should set off alarm bells when you read it. I don't know if any lints can be persuaded to carp about it though since it's 100% legal.

当你阅读它时,应该会敲响警钟。我不知道是否可以说服任何lint来讨论它,因为它是 100% 合法的。