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