简体   繁体   中英

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. 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. I am not sure. Tried gcc and clang no difference. Tried both with stack and heap allocation, as well as 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".

Why does this C++ code runs the destructor 17 times :

#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.

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. 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). 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++ destructors are synchronous while C# "destructors" are asynchronous and may not ever run (definitely not when object is "out of scope" compared to C++).

In C#, your List is storing references to objects. In C++, you are actually storing objects in the vector. 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

#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:

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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