简体   繁体   English

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

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

I want the following code to create 5 objects of the class "test" which call the constructor each time one is created,store them in a vector, print "lalalala" once, and then run the destructors and destroy the created objects. 我希望下面的代码创建“ test”类的5个对象,这些对象每次创建时都会调用构造函数,将它们存储在矢量中,一次打印“ lalalala”,然后运行析构函数并销毁创建的对象。 I want the destructor to run once for each object i created not more than once. 我希望析构函数为我创建的每个对象运行一次以上。

I think C++ in the following example is creating multiple extra copies of objects i do not want or else it calls the destructor way more times that it should. 我认为在下面的示例中,C ++正在创建我不需要的对象的多个额外副本,否则它将以更多的方式调用析构函数。 I am not sure. 我不确定。 Tried gcc and clang no difference. 尝试过gcc和clang没有区别。 Tried both with stack and heap allocation, as well as std::move. 尝试使用堆栈和堆分配以及std :: move。 All produce the same results, way more destructor calls than i asked for. 都产生相同的结果,析构函数调用的方式比我要求的多。

Also i noticed some but not all C++ destructors are called before i print "lalala". 我也注意到在我打印“ lalala”之前调用了一些但不是全部的C ++析构函数。

Why does this C++ code runs the destructor 17 times : 为什么此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;
}

While this C# code does exactly what i want, 5 constructors and 5 destructors. 尽管此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");   
    }
}

Missing copy-constructor in C++ adds mismatch between reported number of constructor calls and destructor calls. C ++中缺少复制构造函数会导致报告的构造函数调用和析构函数调用数量之间不匹配。 There are a lot of copies created (number depends on optimizations performed/allowed by compiler). 创建了很多副本(数量取决于编译器执行/允许的优化)。

Note that you are comparing apples to oranges (twice): 请注意,您正在比较苹果和橙子(两次):

  • C++ objects are by default value types, while C# classes are reference types (and C# value types - struct can't have destructors). 默认情况下,C ++对象是值类型,而C#类是引用类型(和C#值类型- struct不能具有析构函数)。 So if you C++ code would use pointers wrapped into some sort of smart-pointer (thus also avoiding problem with missing copy constructor) you'll get the same behavior. 因此,如果您的C ++代码将使用包装在某种类型的智能指针中的指针(从而也避免了缺少复制构造函数的问题),您将得到相同的行为。

  • C++ destructors are synchronous while C# "destructors" are asynchronous and may not ever run (definitely not when object is "out of scope" compared to C++). C ++析构函数是同步的,而C#“析构函数”是异步的,并且可能永远不会运行(与C ++相比,对象“超出范围”绝对不是)。

In C#, your List is storing references to objects. 在C#中,您的列表存储了对对象的引用。 In C++, you are actually storing objects in the vector. 在C ++中,实际上是将对象存储在向量中。 Which means they need to be copied when they're put into the vector, and also when the vector needs to reallocate. 这意味着在将其放入向量中以及向量需要重新分配时,需要将其复制。 Each one of those copies is a separate object (created with the copy constructor, which you're not tracking), and will have the destructor called on it. 这些副本中的每个副本都是一个单独的对象(使用副本构造函数创建,您无需跟踪),并且将调用析构函数。

A close approximation in C++ to what you are doing in C# would be to store pointers (or smart pointers) to heap allocated test objects, instead of test objects themselves 在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;
}

A preferred idiomatic C++ approach, if you want to be sure you just create 5 objects, but not have to allocate each one individually on the heap would be the following: 如果要确保只创建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