C++;与新概念和范围的混淆 我试图学习C++,从我在书中看到的东西和:
如果我使用C++;与新概念和范围的混淆 我试图学习C++,从我在书中看到的东西和:,c++,vector,scope,C++,Vector,Scope,如果我使用autox=newobject()x是指向对象地址的指针,它位于动态内存中,在我删除它之前一直存在 但是如果我使用对象x或auto x=Object()它只持续到超出范围 在一个例子中,他们展示了这一点: void foo() { Point p = Point(0,0); } // p is now destroyed. 我不明白的是,当我不使用new时返回一个对象会发生什么?它会是该对象的副本吗 以下是一个我不确定的例子: class Object { public:
autox=newobject()
x是指向对象地址的指针,它位于动态内存中,在我删除它之前一直存在
但是如果我使用对象x
或auto x=Object()
它只持续到超出范围
在一个例子中,他们展示了这一点:
void foo()
{
Point p = Point(0,0);
} // p is now destroyed.
我不明白的是,当我不使用new时返回一个对象会发生什么?它会是该对象的副本吗
以下是一个我不确定的例子:
class Object
{
public:
int X;
static Object Foo(int y)
{
Object result;
result.X = y;
return result;
}
};
class TestContainer
{
public:
void Run()
{
for(auto i = 0; i < 10; i++)
{
_objects.at(i) = Object::Foo(i + (rand() % 10 + 1));
}
}
private:
std::vector<Object> _objects;
};
void main()
{
TestContainer tc;
while(true)
{
tc.Run();
}
}
类对象
{
公众:
int X;
静态对象Foo(inty)
{
客观结果;
结果:X=y;
返回结果;
}
};
类TestContainer
{
公众:
无效运行()
{
用于(自动i=0;i<10;i++)
{
_at(i)=对象::Foo(i+(rand()%10+1));
}
}
私人:
std::vector_对象;
};
void main()
{
测试容器tc;
while(true)
{
tc.Run();
}
}
注意,我还没有测试过这段代码,但我认为它消除了我的困惑。在我的主函数中,我实例化TestContainer并无限次地调用它的Run方法。这进而循环调用对象上的静态Foo方法,该方法返回存储在向量中的新对象的副本
我的问题是,所有对象的?如果我用一个新对象替换对象向量中的元素2,旧值现在是否“超出范围”并被删除
它会是该对象的副本吗
对
或者可以使用移动,或者可以优化整个过程,在最终编译的程序中只生成一个实际对象
但是,基本上,是的
如果我用一个新对象替换对象向量中的元素2,旧值现在是否“超出范围”并被删除
对
另外,您正在对不存在的元素使用at
;要添加元素,请使用插入
或推回
它会是该对象的副本吗
对
或者可以使用移动,或者可以优化整个过程,在最终编译的程序中只生成一个实际对象
但是,基本上,是的
如果我用一个新对象替换对象向量中的元素2,旧值现在是否“超出范围”并被删除
对
另外,您正在对不存在的元素使用
at
;要添加元素,请使用insert
或push_back
这样一个简单的类的行为非常类似于POD变量。o1=o2按元素复制字段。因此,赋值的目标对象不会被删除,而是被覆盖
超出范围的对象“走开”(因为堆栈已展开),例如int。像这样的简单类的行为很像POD变量。o1=o2按元素复制字段。因此,赋值的目标对象不会被删除,而是被覆盖
超出范围的对象“走开”(因为堆栈已展开),例如int。这里有一个可运行的示例,我相信它说明了这种行为:
#include <iostream>
using namespace std;
class Foo {
private:
int id;
public:
Foo(int x)
: id(x)
{
cout << this->id << " is created" << endl;
}
Foo(const Foo& rhs)
: id(rhs.id)
{
cout << "copied " << this->id << endl;
}
Foo& operator=(Foo rhs){
this->id=rhs.id;
cout << "assigned " << this->id << endl;
return *this;
}
~Foo(){
cout << this->id << " is destroyed" << endl;
}
int getID(){
return this->id;
}
};
Foo bar(){
Foo f1 = Foo(1);
cout << f1.getID() << " from bar" << endl;
return f1;
}
int main(){
Foo f2 = bar();
cout << f2.getID() << " from main" << endl;
return 0;
}
从这里,我看不到副本或作业。我怀疑发生的是f1和f2都引用了内存中对象的同一个实例。f1引用超出范围时,不会取消分配该对象,因为该对象已分配了另一个引用。以下是一个可运行的示例,我相信它说明了此行为:
#include <iostream>
using namespace std;
class Foo {
private:
int id;
public:
Foo(int x)
: id(x)
{
cout << this->id << " is created" << endl;
}
Foo(const Foo& rhs)
: id(rhs.id)
{
cout << "copied " << this->id << endl;
}
Foo& operator=(Foo rhs){
this->id=rhs.id;
cout << "assigned " << this->id << endl;
return *this;
}
~Foo(){
cout << this->id << " is destroyed" << endl;
}
int getID(){
return this->id;
}
};
Foo bar(){
Foo f1 = Foo(1);
cout << f1.getID() << " from bar" << endl;
return f1;
}
int main(){
Foo f2 = bar();
cout << f2.getID() << " from main" << endl;
return 0;
}
从这里,我看不到副本或作业。我怀疑发生的是f1和f2都引用了内存中对象的同一个实例。f1引用超出范围时,对象未被取消分配,因为该对象已分配了另一个引用。我认为您的
\u对象。at(I)
表达式将抛出,因为\u对象
从未给定大小。@FredLarson:观察得好。是的,谢谢Fred。错过了。警告:auto x=new Object()代码>与auto x=新对象不同代码>。你可能想要后者。更多信息:我想你的\u对象。at(I)
表达式会抛出,因为\u对象从来没有给定大小。@Fredrarson:观察得好。是的,谢谢Fred。错过了。警告:auto x=new Object()代码>与auto x=新对象不同代码>。你可能想要后者。更多信息:这些对象是矢量元素,不存在于“堆栈”上。它们实际上是动态分配的!请不要在使用这些简化术语时混淆。@Lightness:我不是在说矢量元素。我刚刚指出,“对象”(由OP定义)在各个方面的行为都类似于int。当它“超出范围”(范围意味着我们谈论的是局部变量)时,它确实存在于堆栈上,并且不再这样做,与int完全一样。因此来自“=Object::Foo(I+(rand()%10+1))”的临时对象一旦执行离开语句,就不再存在,就像int(2)一样。这可能会让人困惑,但它很好,因为它解决了“所有对象发生了什么”的问题;-)。无论如何,OP是询问向量的元素。所以,这个答案充其量是无关紧要的!:)谢谢你的微笑。。。只是OP问“当我不使用new时返回一个对象会发生什么?它会是该对象的一个副本吗?”我回答说,不是更多,不是更少——几乎不相关。如果我读对了你的答案,我们说了同样的话。你说的堆栈是错误的。我没有。这些对象是向量元素,不存在于“堆栈”上。它们实际上是动态分配的!请不要在使用这些简化术语时混淆。@Lightness:我不是在说矢量元素。我只是指出一个“对象”(由OP定义)在各个方面的行为都像一个int