53

首先我来自JAVA。

在java中,我们像这样创建类对象。

Example example=new Example();

Example 类可以有构造函数,也可以不能有构造函数。

我可以像这样在 c++ 中使用相同的

Example* example=new Example();

构造函数是强制性的。

从本教程http://www.cplusplus.com/doc/tutorial/classes/

我知道我们可以像这样创建对象。

Example example;

不需要构造函数。

我有两个问题。

  1. 两种创建类对象的方式有什么区别。

  2. 如果我正在创建对象,例如Example example;如何在单例类中使用它。

就像我通常那样做。

Sample* Singleton::get_sample() {
    if (sample == NULL) {
        sample = new Sample();
    }
    return sample;
}

如果我错了,请指导我。

4

8 回答 8

56

我可以像这样在 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;

};
于 2013-03-09T12:58:17.267 回答
34
Example example;

这是一个名为exampletype的变量的声明Example。这将默认初始化涉及调用其默认构造函数的对象。该对象将具有自动存储持续时间,这意味着它将在超出范围时被销毁。

Example* example;

这是一个名为的变量的声明,它是example一个指向Example. 在这种情况下,默认初始化使其未初始化 - 指针没有特别指向任何地方。这里没有Example对象。指针对象具有自动存储期限。

Example* example = new Example();

这是一个名为的变量的声明,它是example一个指向Example. 如上所述,此指针对象具有自动存储持续时间。然后使用 的结果对其进行初始化new Example();。此new表达式创建一个Example具有动态存储持续时间的对象,然后返回一个指向它的指针。所以example指针现在指向那个动态分配的对象。该Example对象是值初始化的,如果有一个,它将调用用户提供的构造函数,否则将所有成员初始化为 0。

Example* example = new Example;

这与上一行类似。不同之处在于Example对象是默认初始化的,它将调用的默认构造函数Example(或者如果它不是类类型,则保持未初始化)。

动态分配的对象必须是deleted (可能带有delete example;)。

于 2013-03-09T12:55:41.693 回答
8

在 C++ 中有两种方法可以创建/创建对象。

第一个是:

MyClass myclass; // if you don;t need to call rather than default constructor    
MyClass myclass(12); // if you need to call constructor with parameters

第二个是:

MyClass *myclass = new MyClass();// if you don;t need to call rather than default constructor
MyClass *myclass = new MyClass(12);// if you need to call constructor with parameters

在 c++ 中,如果使用 new 关键字,对象将存储在堆中。如果您长时间使用此对象并且使用第一种方法,它将非常有用,它将存储在堆栈中。它只能在很短的时间内使用。注意:如果你使用 new 关键字,记住它会返回指针值。您应该用 * 声明名称。如果您使用第二种方法,它不会删除堆中的对象。您必须使用 delete 关键字自行删除;

delete myclass;
于 2016-10-21T06:24:07.560 回答
3

1)两种创建类对象的方式有什么区别。

第一个是指向堆中构造对象的指针(by new)。第二个是隐式构造的对象。(默认构造函数)

2)如果我正在创建像示例示例这样的对象;如何在单例类中使用它。

这取决于您的目标,最简单的方法就是简单地将其作为班级成员。

具有类对象的单例类示例Example

class Sample
{

    Example example;

public:

    static inline Sample *getInstance()
    {
        if (!uniqeInstance)
        {
            uniqeInstance = new Sample;
        }
        return uniqeInstance;
    }
private:
    Sample();
    virtual ~Sample();
    Sample(const Sample&);
    Sample &operator=(const Sample &);
    static Sample *uniqeInstance;
};
于 2013-03-09T12:54:25.023 回答
3

1)两种创建类对象的方式有什么区别。

a) 指针

Example* example=new Example();
// you get a pointer, and when you finish it use, you have to delete it:

delete example;

b) 简单声明

Example example;

你得到一个变量,而不是一个指针,它将在声明的范围之外被销毁。

2) 单例 C++

这个 SO question可以帮助你

于 2013-03-09T12:55:28.473 回答
3

首先,这两种情况都调用了构造函数。如果你写

Example *example = new Example();

然后您正在创建一个对象,调用构造函数并检索指向它的指针

如果你写

Example example;

唯一的区别是您获取的是对象而不是指向它的指针。在这种情况下调用的构造函数与上面相同,默认(无参数)构造函数。

至于单例问题,您必须通过编写简单地调用您的静态方法:

Example *e = Singleton::getExample();
于 2013-03-09T12:56:11.770 回答
2
Example example;

这里的例子是堆栈上的一个对象。

Example* example=new Example();

这可以分为:

Example* example;
....
example=new Example();

这里第一条语句创建了一个变量示例,它是一个“指向示例的指针”。调用构造函数时,会在堆上为其分配内存(动态分配)。当不再需要该内存时,程序员有责任释放它。(C++ 没有像 java 这样的垃圾收集)。

于 2013-03-09T12:54:48.940 回答
2

在第一种情况下,您在heapusing上创建对象new。在第二种情况下,您是在 上创建对象stack,因此超出范围时将被处理掉。在您不再需要它们时,您需要在明确使用时C++删除它们。heapdelete

要从类中调用静态方法,请执行

Singleton* singleton = Singleton::get_sample();

在您的主要功能或任何地方。

于 2013-03-09T12:55:01.640 回答