【问题标题】:C++ Object without new没有新的 C++ 对象
【发布时间】:2010-12-18 09:37:26
【问题描述】:

这是一个非常简单的问题,但我多年来一直没有正确地使用 C++,所以我对此感到有些困惑。此外,在互联网上查找并不是最容易的事情(至少对我而言),而不是尝试。

为什么不使用new 关键字,它是如何工作的?

基本上,这里发生了什么?

CPlayer newPlayer = CPlayer(position, attacker);

【问题讨论】:

    标签: c++ new-operator


    【解决方案1】:

    这个表达式:

    CPlayer(position, attacker)
    

    使用上面的构造函数创建一个CPlayer类型的临时对象,然后:

    CPlayer newPlayer =...;
    

    使用复制构造函数将提到的临时对象复制到newPlayer。更好的方法是编写以下内容以避免临时性:

    CPlayer newPlayer(position, attacker);
    

    【讨论】:

    • 其实编译器可能会优化它。在这种情况下,复制构造函数将不会被调用。 stackoverflow.com/questions/1758142/…
    • 声明中的赋值并不比使用构造函数语法效率低。如果它们是单独的陈述,那么关于临时的评论将是正确的。本质是,这声明了一个 CPlayer(通常在堆栈上),而不是从空闲存储(堆)中为其分配空间。
    • 不,几乎按照定义:堆栈上的对象仅在它们处于范围内时才存在。 stackoverflow.com/search?q=%5Bc%2B%2B%5D+stack+heap
    • 我认为这个答案并不完全正确。 OP 的代码 looks 就像是创建一个临时代码然后复制它,但标准 12.1.11 另有建议。这只是一个普通的构造函数调用,这是 jleedev 发现的。
    • 是否删除副本由编译器决定(在允许的情况下)。 12.8/15.
    【解决方案2】:

    上面在堆栈上构造了一个 CPlayer 对象,因此它不需要new。如果你试图在堆上分配一个 CPlayer 对象,你只需要使用new。如果您使用堆分配,则代码如下所示:

    CPlayer *newPlayer = new CPlayer(position, attacker);
    

    请注意,在这种情况下,我们使用了一个指向 CPlayer 对象的指针,该对象需要通过对 delete 的匹配调用来清理。分配在堆栈上的对象会在超出范围时自动销毁。

    实际上写起来会更容易更明显:

    CPlayer newPlayer(position, attacker);
    

    无论如何,很多编译器都会优化您发布到上面的版本,并且更清晰。

    【讨论】:

    • 我不认为这是正确的:“在堆上分配的对象将在超出范围时自动销毁。”
    • 你是对的,我的意思是写“堆栈”,而不是“堆”。感谢您指出这一点。
    • 同意这一点。我们应该保持 C++ 代码与 C 代码相同的风格。所以CPlayer newPlayer(position, attacker);CPlayer newPlayer = CPlayer(position, attacker);创建栈变量要好。
    【解决方案3】:
    CPlayer newPlayer = CPlayer(position, attacker);
    

    这一行创建了一个新的 CPlayer 类型的本地对象。尽管它的外观类似函数,但这只是调用了 CPlayer 的构造函数。不涉及临时或复制。名为 newPlayer 的对象与它所包含的作用域一样长。此处不要使用 new 关键字,因为 C++ 不是 Java。

    CPlayer* newPlayer = new CPlayer(position, attacker);
    

    这一行在堆上构造了一个 CPlayer 对象,并定义了一个名为 newPlayer 的指针指向它。该对象一直存在,直到有人 deletes 为止。

    【讨论】:

    • “不涉及临时性或复制”——这并不完全正确。没有这样的保证。但是每个体面的编译器都应该省略副本。
    【解决方案4】:

    newPlayer 不是动态分配的变量,而是自动堆栈分配的变量:

    CPlayer* newPlayer = new CPlayer(pos, attacker);
    

    不同于

    CPlayer newPlayer = CPlayer(pos, attacker);
    

    newPlayer 是通过正常的 CPlayer(position, attacker) 构造函数调用在堆栈上分配的,尽管比通常的要冗长一些

    CPlayer newPlayer(pos, attacker);
    

    基本上和说的一样:

    int i = int(3);
    

    【讨论】:

    • 这里要小心。这是一个“复制初始化”。这不是作业。
    • 我的立场是正确的,这不是作业;甚至不涉及复制构造函数。相应地编辑答案。
    • 当然,复制ctor(至少在逻辑上)参与其中。您会注意到,如果您将复制 ctor 设为私有。然后,此复制初始化将不再起作用。即使编译器能够优化副本,C++ 标准也需要可访问的副本 ctor。
    • 不,新分配在堆上,你的第二个玩家在堆栈上思考
    猜你喜欢
    • 2011-03-11
    • 2020-08-31
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 2020-06-25
    • 2016-07-13
    相关资源
    最近更新 更多