C++中的构造函数和析构函数与C#比较
我想要下面的代码创建5个类“test”的对象,每次创建时调用构造函数,将它们存储在一个向量中,打印“lalalala”一次,然后运行析构函数并销毁创建的对象。我希望析构函数为我创建的每个对象运行一次,但不要超过一次。C++中的构造函数和析构函数与C#比较
我认为在下面的例子中,C++创建了多个不需要的对象的副本,否则它会调用析构函数多次。我不确定。试过海湾合作委员会和铿锵没有区别。尝试堆栈和堆分配,以及std :: move。所有产生相同的结果,方式更多的析构函数调用比我所要求的。
另外我注意到一些但不是所有的C++析构函数在我打印“lalala”之前调用。
为什么这个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#中的所作所为将存储指针(或智能指针)堆中分配的测试对象,而不是测试对象本身
#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;
}
优选的惯用C++的做法,如果你想确保你只是创建5个对象,但不必分配在堆上的每个对象将是以下内容:
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;
}
在C++中缺少复制构造函数会增加构造函数调用和析构函数调用的报告数量之间的不匹配。有很多副本创建(数量取决于执行/编译器允许的优化)。
注意,你是比较苹果和橘子(两次):
C++对象是默认值类型,而C#类是引用类型(和C#的值类型 -
struct
不能有析构函数) 。所以,如果你的C++代码会使用包装成某种智能指针的指针(这样也避免了缺少复制构造函数的问题),你会得到相同的行为。C++析构函数是同步的,而C#“析构函数”是异步的,并且可能永远不会运行(与C++相比,当对象超出范围时肯定不会运行)。
您还需要计数复制构造函数。 – SergeyA
http://stackoverflow.com/a/2625089/1060270说明可能有帮助 – amit