首先我来自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;
}
如果我错了,请指导我。
答案 0 :(得分:26)
我可以在c ++中使用相同的[...]其中构造函数是必需的。从this tutorial我得到了我们可以创建这样的对象[...]不需要构造函数。
这是错误的。构造函数必须存在才能创建对象。如果你不提供任何条件,构造函数可以在某些条件下由编译器隐式定义,但如果你想要实例化对象,最终构造函数必须在那里。实际上,对象的生命周期定义为在构造函数例程返回时开始。
来自C ++ 11标准的第3.8 / 1段:
[...]类型为T的对象的生命周期始于:
- 获得具有类型T的正确对齐和大小的存储,并且
- 如果对象具有非平凡的初始化,则其初始化完成。
因此,必须存在构造函数。
1)创建类对象的方式之间有什么区别。
实例化具有自动存储持续时间的对象时,如下所示(其中X
是某个类):
X x;
您正在创建一个对象,当该对象超出范围时将自动销毁。另一方面,当你这样做:
X* x = new X();
您正在动态创建对象,并且您将其地址绑定到指针。这样,当x
指针超出范围时,您创建的对象 not 将被销毁。
在Modern C ++中,这被认为是一种可疑的编程实践:尽管指针很重要,因为它们允许实现 reference semantics ,但原始指针很糟糕,因为它们很糟糕可能导致内存泄漏(对象超出所有指针而永远不会被破坏)或悬空指针(指针超出他们指向的对象,在解除引用时可能导致未定义的行为)。
事实上,在使用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;
};
答案 1 :(得分:18)
Example example;
这是类型example
的名为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
的默认构造函数(如果它不是类类型,则保持未初始化)。
动态分配的对象必须为delete
d(可能带有delete example;
)。
答案 2 :(得分:3)
1)创建课程的方式有什么不同 对象。
第一个是指向堆中构造对象的指针(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;
};
答案 3 :(得分: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)Singleton C ++
This SO question可以帮助您
答案 4 :(得分:3)
首先,两种情况都会调用构造函数。如果你写
Example *example = new Example();
然后你正在创建一个对象,调用构造函数并检索指向它的指针。
如果你写
Example example;
唯一的区别是你得到的是对象而不是指向它的指针。在这种情况下调用的构造函数与上面相同,默认(无参数)构造函数。
至于单例问题,您必须通过编写简单的方法来调用静态方法:
Example *e = Singleton::getExample();
答案 5 :(得分:2)
Example example;
这里的例子是堆栈中的一个对象。
Example* example=new Example();
这可以分解为:
Example* example;
....
example=new Example();
这里第一个语句创建一个变量示例,它是“指向Example的指针”。调用构造函数时,会在堆上为其分配内存(动态分配)。程序员有责任在不再需要时释放这些内存。 (C ++没有像java这样的垃圾收集。)
答案 6 :(得分:2)
在第一种情况下,您使用heap
在new
上创建对象。
在第二种情况下,您在stack
上创建对象,因此在超出范围时将被处置掉。
在C++
中,当您不再需要时,您需要使用heap
明确删除delete
上的对象。
要从类中调用静态方法,请执行
Singleton* singleton = Singleton::get_sample();
在您的主要功能或任何地方。
答案 7 :(得分:2)
在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 myclass;