C++ 什么';c+中int i=0,int i(0),int*p=new int,int*p=new int(0)之间的s差+;
两者有什么区别C++ 什么';c+中int i=0,int i(0),int*p=new int,int*p=new int(0)之间的s差+;,c++,C++,两者有什么区别 int i=0; 及 及 int*p=newint仍然是复制初始样式吗 何时使用inti=0notnew int(0)?new意味着堆内存分配(可能会泄漏),所以不,您不想一直这样做 inti=0和inti(0)是等效的,但取决于实现,第一个可以使用赋值运算符,而第二个可以使用值构造。这可以让编译器针对目标体系结构进行优化。在类的情况下,赋值方法可能会慢一些,因为它将创建一个类(通常带有默认值),然后它将执行赋值并清除它刚刚分配的所有默认值 有人可能会插话并参考语言规范以获得
int i=0;
及
及
int*p=newint
仍然是复制初始样式吗
何时使用
inti=0
notnew int(0)
?new
意味着堆内存分配(可能会泄漏),所以不,您不想一直这样做
inti=0代码>和inti(0)
是等效的,但取决于实现,第一个可以使用赋值运算符,而第二个可以使用值构造。这可以让编译器针对目标体系结构进行优化。在类的情况下,赋值方法可能会慢一些,因为它将创建一个类(通常带有默认值),然后它将执行赋值并清除它刚刚分配的所有默认值
有人可能会插话并参考语言规范以获得更准确的答案。new
意味着堆内存分配(可能会泄漏),因此不,您不想一直这样做
inti=0代码>和inti(0)
是等效的,但取决于实现,第一个可以使用赋值运算符,而第二个可以使用值构造。这可以让编译器针对目标体系结构进行优化。在类的情况下,赋值方法可能会慢一些,因为它将创建一个类(通常带有默认值),然后它将执行赋值并清除它刚刚分配的所有默认值
有人可能会在语言规范中加入和引用更准确的答案。 < P>在C和早期C++中,只能使用int i=0;
inti(0)代码>模式与常规类型的构造函数相同
T i(0);
因此,它被添加为int i=0的替代品代码>看起来不像一般的构造函数模式。这在使用模板时非常有用。因此,模板可以使用int和类。在c和早期C++中,< p>只能使用int i=0;
inti(0)代码>模式与常规类型的构造函数相同
T i(0);
因此,它被添加为int i=0的替代品代码>看起来不像一般的构造函数模式。这在使用模板时非常有用。因此模板可以使用int和类。我将首先回答一个稍微不同的问题
假设您有一个类
或结构
(它们几乎相同),如下所示:
struct Foo {
int value; // Foo stores an int, called value
Foo(int v):value(v) {}; // Foo can be constructed (created) from an int
explicit Foo(double d):value(d) {}; // Foo can be constructed (created) from a double
// ^^^ note that keyword. It says that it can only be EXPLICITLY created from a double
};
现在,这很像int
,但有一些区别
Foo i = 0;
上面创建了一个int
literal,然后使用Foo(intv)
构造函数构造fooi
Foo i(0);
上面创建了一个int
literal,然后使用Foo(intv)
构造函数构造fooi
。注意,我只是重复了我自己
Foo i = Foo(0);
上面创建一个int
literal,然后使用Foo(intv)
构造函数构造fooi
,然后从中复制构造fooi
。但是,该标准允许编译器“省略”(跳过)复制构造函数,而只是直接从int
literal0
构造fooi
Foo* i = new Foo;
这将进入空闲存储(通常实现并称为堆),获得足够的内存来存储Foo
,然后默认构造它。然后它返回此Foo
对象的地址,然后使用该地址初始化指针Foo*i
。现在,请注意Foo
的默认构造函数未初始化value
。这是我在上述Foo
实现中的一个缺陷(在我看来),除非在特殊情况下,否则您很少希望这样做
令人烦恼的是,整数(char
,int
,long
,无符号字符
,等等),浮点(double
或float
)文本和指针文本都共享此属性——默认情况下,它们不会初始化为任何值
因此,您应该确保它们已显式初始化。对于Foo
,添加一行:
Foo():value() {}
这就足够了
Foo* i = new Foo(0);
这将进入空闲存储(通常实现并称为堆),获得足够的内存来存储Foo
,然后使用整数文本0构造它。然后它返回此Foo
对象的地址,然后使用该地址初始化指针Foo*i
现在,免费存储中的内存通常会保留下来供您使用,直到您有时间归还它,或者您的程序关闭。为了返回它,您在同一个指针上调用delete
,这两种情况下,对象(Foo
在本例中)的析构函数都被调用(Foo
没有析构函数,因此这被跳过),然后内存被返回到空闲存储区,供以后调用new
使用
跟踪这一点是一件非常痛苦的事情,也是一大堆错误的根源,因此您应该避免调用new
。有很多方法可以避免调用new
,包括使用std::vector
来管理内存块,或者使用shared_ptr
和make_shared
在堆上创建对象,这些对象通过一种称为RAII的技术来管理自己的生命周期,或者,当您希望对指针的生命周期进行密切控制时,可以使用unique\u ptr
(遗憾的是,make\u unique
不存在)
现在让我们更进一步
Foo i = 0.0;
这无法编译。我说过Foo(double)
的构造函数是显式的,上面只选择调用非显式的构造函数。另一方面:
Foo i(0.0);
Foo i = Foo(0.0);
它们都愿意调用显式构造函数,并且工作得很好
东北
Foo i(0.0);
Foo i = Foo(0.0);
Foo i{0.0};
Foo i = {0};
int i = 0;
int i(0);
int i = int();
int i();
int i{};
int* p = new int;
int *p=new int(0);
int x(int());
int x();
int i=0;
int i(0);
int *p=new int;
int *p=new int(0);