c++与new和scope的混淆

C++ confusion with new and scope

本文关键字:scope new c++      更新时间:2023-10-16

我正在努力学习c++,从我在书中读到的东西和SO:

如果我使用auto x = new Object();, x是一个指向对象地址的指针,它在动态内存中,直到我删除它。

然而,如果我使用Object 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();
    }
}

注意我没有测试过这段代码,但我认为它消除了我的困惑。在我的主函数我实例化TestContainer和无尽调用它的运行方法。这反过来循环调用Object的静态Foo方法,返回存储在vector中的新Object的副本。

我的问题是,所有的对象发生了什么?如果我用新对象替换对象向量中的元素2,旧值现在是否"超出范围"并被删除?

将是对象的副本吗?

是的。

或者可以使用移动,或者可以优化整个东西,以便在最终编译的程序中只产生一个实际对象。

但是,基本上,是的。

如果我用新对象替换对象向量中的元素2,旧值现在是否"超出范围"并被删除?

是的。

作为题外话,您在不存在的元素上使用at;要添加元素,请使用insertpush_back

这样一个简单的类的行为很像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;
}

产生如下输出:

1 is created
1 from bar
1 from main
1 is destroyed

从这里,我没有看到副本或作业。我怀疑发生的事情是f1和f2都引用了内存中对象的相同实例。当f1引用超出作用域时,对象不会被取消分配,因为对象有另一个引用分配给它。