繁体   English   中英

与C#相比,C ++中的构造方法和析构方法

[英]Constructors and Destructors in C++ compared to C#

我希望下面的代码创建“ test”类的5个对象,这些对象每次创建时都会调用构造函数,将它们存储在矢量中,一次打印“ lalalala”,然后运行析构函数并销毁创建的对象。 我希望析构函数为我创建的每个对象运行一次以上。

我认为在下面的示例中,C ++正在创建我不需要的对象的多个额外副本,否则它将以更多的方式调用析构函数。 我不确定。 尝试过gcc和clang没有区别。 尝试使用堆栈和堆分配以及std :: move。 都产生相同的结果,析构函数调用的方式比我要求的多。

我也注意到在我打印“ lalala”之前调用了一些但不是全部的C ++析构函数。

为什么此C ++代码运行析构函数17次:

#include <iostream>
#include <vector>

using namespace std;


class test
{
public:
    int t;
    test(int i)
    {
        t = i;
        cout << "Created instance " << t << ". \n";
    }
    ~test()
    {
        cout << "(*)Deleted instance " <<  t <<  ".\n";
    }
};

int main()
{
    vector <test> V;

    for(int i = 1; i <= 5; i++)
    {
        test D(i);
        V.push_back(D);
    }
   cout << "LALALLALA \n";
   return 0;
}

尽管此C#代码完全符合我的要求,但5个构造函数和5个析构函数。

using System.IO;
using System;
using System.Collections.Generic;
class Program
{
    class test
    {
        public int t;
        public test(int i)
        {
            t = i;
            Console.Write ("Created instance ");
            Console.Write (t.ToString());
            Console.WriteLine(".");
        }

        ~test()
        {
            Console.Write( "(*)Deleted instance ");
            Console.Write(t.ToString());
            Console.WriteLine(".");
        }

    }
    static void Main()
    {
        List<test> lst = new List<test>();
        for(int i = 0; i < 5; i++)
        {
            test temp = new test(i);
            lst.Add(temp);
        }
        Console.WriteLine("LALALLALA \n");   
    }
}

C ++中缺少复制构造函数会导致报告的构造函数调用和析构函数调用数量之间不匹配。 创建了很多副本(数量取决于编译器执行/允许的优化)。

请注意,您正在比较苹果和橙子(两次):

  • 默认情况下,C ++对象是值类型,而C#类是引用类型(和C#值类型- struct不能具有析构函数)。 因此,如果您的C ++代码将使用包装在某种类型的智能指针中的指针(从而也避免了缺少复制构造函数的问题),您将得到相同的行为。

  • C ++析构函数是同步的,而C#“析构函数”是异步的,并且可能永远不会运行(与C ++相比,对象“超出范围”绝对不是)。

在C#中,您的列表存储了对对象的引用。 在C ++中,实际上是将对象存储在向量中。 这意味着在将其放入向量中以及向量需要重新分配时,需要将其复制。 这些副本中的每个副本都是一个单独的对象(使用副本构造函数创建,您无需跟踪),并且将调用析构函数。

在C ++中,与您在C#中所做的工作非常相似的是将存储存储分配的测试对象的指针(或智能指针),而不是测试对象本身

#include <memory> // for shared_ptr

int main()
{
    std::vector<std::shared_ptr<test>> V;

    for(int i = 1; i <= 5; i++)
    {
        auto D = std::make_shared<test>(i);
        V.push_back(D);
    }
    std::cout << "LALALLALA \n";
    return 0;
}

如果要确保只创建5个对象,而不必在堆上单独分配每个对象,则首选的惯用C ++方法如下:

int main()
{
    std::vector<test> V;

    // ensure we can store 5 objects without reallocating
    V.reserve(5);

    for(int i = 1; i <= 5; i++)
    {
        // construct the object in place in the vector
        V.emplace_back(i);
    }
    std::cout << "LALALLALA \n";
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM