C++ 如果我声明一个没有名字的类实例,它会留在内存中吗?
我有以下代码(我将跳过包含的内容和您拥有的内容): main.cppC++ 如果我声明一个没有名字的类实例,它会留在内存中吗?,c++,class,vector,instance,member,C++,Class,Vector,Instance,Member,我有以下代码(我将跳过包含的内容和您拥有的内容): main.cpp std::vector <actor> actors; int main() { actor (2, 3); } actor.cpp extern std::vector <actor> actors; actor::actor(int x, int y) { actor::x = x; actor::y = y; actors.push_back(*this); }
std::vector <actor> actors;
int main() {
actor (2, 3);
}
actor.cpp
extern std::vector <actor> actors;
actor::actor(int x, int y)
{
actor::x = x;
actor::y = y;
actors.push_back(*this);
}
除了被推送到actors向量的一个实例之外,实际上还创建了一个actor实例吗
注意:如果代码没有编译,请忽略任何错误。实际代码确实可以编译,但是太复杂了,无法真正粘贴到这里。它在表达式求值期间保持“活动”,它是表达式的一部分,并在求值后立即自动处理
例如:
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 (2, 3)
actor (2, 3)
除了被推送到actors向量的一个实例之外,实际上还创建了一个actor实例吗
对actor(2,3)
将创建类型为actor
的临时对象,除非它是未计算的表达式的一部分1。在这个临时表达式的构造函数中,(this)的一个副本将被推送到堆栈上(但再次注意,在未赋值表达式中,构造函数当然不会被调用)
在包含actor(2,3)
的表达式末尾,临时变量将被销毁。矢量副本将保持不变
1未赋值表达式是(…)、
typeid(…)
、decltype(…)
或noexcept(…)
表达式中的表达式。您忘记在语句末尾放置分号了
actor (2, 3)
一定有
actor(2, 3);
当控件传递给下一个语句时,此行中创建的临时对象将在同一行中删除。它的副本(对象的副本)将由向量中的构造函数推送
因此,向量中只有一个类型为actor的对象
如果要定义由该对象初始化的常量引用,则可以保留临时对象。比如说
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;
}
在本例中,程序输出两个不同对象的值。不清楚。OP的代码不编译,如果表达式是
sizeof(actor(2,3))
,则不会发生推送。没有人提到sizeof
,OP只询问特定行actor(2,3)
@KonradRudolph:关键是并不是每个表达式都会被计算,并且只有在计算发生时才会产生预期的副作用。我认为这是一个非常普遍的观点,值得一提。1的答案是唯一的C++答案,所以用一个有意义的方式“推到堆栈”这个短语。@ KerrekSB很有趣,因为它实际上是偶然的(我是说<代码>向量< /代码>)。p但是我会让它保持不变,因为它是准确的。作为对你笔记的回复:你的工作是制作一个最小的例子,它精确地展示了正在仔细研究的问题。如果实际的代码太复杂,请删减它,或者构建一个最小的编译示例。事实上,这是一个写得非常好的问题,“甚至在std::endl流媒体之前”——嗯。你确定吗?我当时的印象是(事实上,我现在仍然是!)这是错误的。子表达式的求值顺序完全未定义。(编辑:)@KonradRudolph-正确,尽管在我的示例中子表达式的顺序明显是从左到右,但我已经更新了答案
const actor &ar = actor( 2, 3 );
#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