【问题标题】:If I declare a class instance with no name, will it stay in memory?如果我声明一个没有名称的类实例,它会留在内存中吗?
【发布时间】:2014-02-18 21:33:06
【问题描述】:

我有以下代码(我会跳过包含和你有什么):

main.cpp

std::vector <actor> actors;
int main() {
    actor (2, 3);
}

演员.h

class actor
{
public:
    int x, y;
    actor(int, int);
};

actor.cpp

extern std::vector <actor> actors;
actor::actor(int x, int y)
{
    actor::x = x;
    actor::y = y;
    actors.push_back(*this);
}

行会:

    actor (2, 3)

除了被推送到actors向量的那个之外,实际上创建一个actor的实例吗?

注意:如果代码无法编译,请忽略任何错误。实际代码确实可以编译,但过于复杂,无法实际粘贴到此处。

【问题讨论】:

  • 回复您的说明:您的工作是制作一个最小的示例,该示例准确地展示了此处审查的问题。如果实际代码太复杂,请修剪它,或者构建一个可以编译的最小示例。这实际上是一个写得很好的问题。

标签: c++ class vector instance member


【解决方案1】:

行会:

actor (2, 3)

除了被推送到actors向量的那个之外,实际上创建一个actor的实例吗?

是的。 actor(2, 3) 将创建一个 actor 类型的 临时 对象,除非它是未计算的表达式的一部分1。在这个临时的构造函数中,一个(*this)的副本将被压入堆栈(但再次注意,在未计算的表达式中,构造函数当然不会被调用)。

在包含actor(2, 3) 的表达式的末尾,临时对象将被销毁。矢量副本将保持不变。


1 未计算的表达式是sizeof(…)typeid(…)decltype(…)noexcept(…) 表达式中的表达式。

【讨论】:

  • 不清楚。 OP的代码无法编译,如果表达式为sizeof(actor(2, 3)),则不会进行推送。
  • 没有人提到sizeof,OP只问了具体行actor(2, 3);
  • @KonradRudolph:关键是不是每个表达式都被评估,并且只有在评估发生时才会发生所需的副作用。我认为这是一个足够笼统的观点,值得一提。
  • +1 是关于 SO 的唯一 C++ 答案,它以有意义的方式使用“推入堆栈”这一短语。
  • @KerrekSB 这很有趣,因为它实际上是一种意外(我的意思是vector)。 :p 但我会让它保持不变,因为它是准确的。
【解决方案2】:

它在对其所属的表达式进行求值期间保持“活动”状态,并在之后立即自动处理。

例子:

actor(2,3); // created and immediately destroyed
actor(2,3)->act(); // created, then acts, then destroyed
std::cout << actor(2,3) << std::endl; // created, streamed, destroyed

知道了(永远不要这样做)

actor const& shoot_myself(actor const& a) { return a; }
...
actor const& a = shoot_myself(actor(2,));
a->act(); // "segmentation fault / core dumped"

【讨论】:

  • “甚至在 std::endl 流式传输之前” – 嗯。你确定吗?我的印象是(事实上,我仍然是!)这是错误的。子表达式的求值顺序是完全未定义的。 (编辑:yup, it’s wrong
  • @KonradRudolph - 正确,虽然在我的示例中子表达式的顺序显然是从左到右,但我已经更新了答案
【解决方案3】:

你忘了在语句末尾加分号

actor (2, 3)

应该有

actor(2, 3);

在将控制传递到下一条语句时,将在同一行中删除在该行中创建的临时对象。它的副本(对象的副本)将由向量中的构造函数推送。

因此,向量中只有一个 actor 类型的对象。

如果您要定义由该对象初始化的 const 引用,则可以保留临时对象。例如

const actor &ar = actor( 2, 3 );

在这种情况下,您有两个类型为 actor 的对象,它们将被推送到向量中,而这个临时对象将被 const 引用引用。

这里有一个例子来说明所说的内容。

#include <iostream>
#include <vector>


struct A
{
    int x, y;
    A (int, int);
};

std::vector<A> v;

A::A( int x, int y ) : x( x ), y( y )
{
    v.push_back( *this );   
}

int main() 
{
    const A &ra = A( 2, 3 );

    std::cout << "ra.x = " << ra.x << ", ra.y = " << ra.y << std::endl;
    std::cout << "v[0].x = " << v[0].x << ", v[0].y = " << v[0].y << std::endl;

    return 0;
}

输出是

ra.x = 2, ra.y = 3
v[0].x = 2, v[0].y = 3

在本例中,程序输出两个不同对象的值。

【讨论】:

    猜你喜欢
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    • 2019-04-08
    • 1970-01-01
    相关资源
    最近更新 更多