我可以像这样在 C++ 中使用相同的 [...] 构造函数是强制性的。从本教程中我了解到我们可以创建这样的对象 [...] 不需要构造函数。
这是错误的。必须存在构造函数才能创建对象。如果您不提供任何构造函数,则编译器可以在某些条件下隐式定义构造函数,但如果您希望实例化对象,最终构造函数必须存在。事实上,对象的生命周期被定义为在构造函数例程返回时开始。
来自 C++11 标准的第 3.8/1 段:
[...] T 类型对象的生命周期开始于:
— 获得了类型 T 的正确对齐和大小的存储,并且
— 如果对象有非平凡的初始化,它的初始化就完成了。
因此,必须存在构造函数。
1)两种创建类对象的方式有什么区别。
当您实例化具有自动存储持续时间的对象时,如下所示(X
某些类在哪里):
X x;
您正在创建一个对象,当它超出范围时将自动销毁。另一方面,当你这样做时:
X* x = new X();
您正在动态创建一个对象,并将其地址绑定到一个指针。这样,当您的指针超出范围时,您创建的对象不会被销毁。x
在现代 C++ 中,这被认为是一种可疑的编程实践:尽管指针很重要,因为它们允许实现引用语义,但原始指针是不好的,因为它们可能导致内存泄漏(对象超过其所有指针并且永远不会被销毁)或悬空指针(指针超过它们指向的对象,在取消引用时可能导致未定义行为)。
事实上,当使用 来创建对象时new
,您必须始终记住使用 来销毁它delete
:
delete x;
如果您需要引用语义并且被迫使用指针,那么在 C++11 中您应该考虑使用智能指针:
std::shared_ptr<X> x = std::make_shared<X>();
智能指针负责处理内存管理问题,这让您对原始指针感到头疼。事实上,智能指针与 Java 或 C# 对象引用几乎相同。“几乎”是必要的,因为程序员必须注意不要通过拥有智能指针来引入循环依赖。
2)如果我正在创建像示例示例这样的对象;如何在单例类中使用它。
你可以做这样的事情(简化代码):
struct Example
{
static Example& instance()
{
static Example example;
return example;
}
private:
Example() { }
Example(Example const&) = delete;
Example(Example&&) = delete;
Example& operator = (Example const&) = delete;
Example& operator = (Example&&) = delete;
};