what's difference between
之间的区别是什么
int i=0;
and
和
int i(0);
int *p=new int;
and
和
int *p=new int(0);
is int *p=new int
is still copy initial style?
int *p=new int仍然是复制初始样式吗?
when to use int i=0;
not new int(0)
?
何时使用int i=0;不是新int(0)?
4 个解决方案
#1
5
I'm going to answer a slightly different question first.
我先回答一个稍微不同的问题。
Suppose you have a class
or struct
(they are pretty much the same) that looks like this:
假设您有一个类或结构(它们几乎是相同的):
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
};
now, this is much like an int
, but there are a few differences.
现在,这很像int,但是有一些区别。
Foo i = 0;
the above creates an int
literal, then constructs Foo i
with it using the Foo(int v)
constructor.
上面创建了一个int文字,然后使用Foo(int v)构造函数构造Foo i。
Foo i(0);
the above creates an int
literal, then constructs Foo i
with it using the Foo(int v)
constructor. Note that I just repeated myself.
上面创建了一个int文字,然后使用Foo(int v)构造函数构造Foo i。注意,我只是重复了一遍。
Foo i = Foo(0);
the above creates an int
literal, then constructs Foo i
with it using the Foo(int v)
constructor, then copy-constructs Foo i
from it. However, the standard allows the compiler to "elide" (skip) the copy constructor, and instead just construct Foo i
directly from the int
literal 0
.
上面创建了一个int文字,然后使用Foo(int v)构造函数构造Foo i,然后从它复制构造Foo i。但是,该标准允许编译器“省略”(跳过)复制构造函数,而是直接从int文字0构造Foo i。
Foo* i = new Foo;
this goes to the free store (typically implemented and called the heap), gets ahold of enough memory to store a Foo
, then default constructs it. It then returns the address of this Foo
object, which is then used to initialize the pointer Foo* i
. Now, note that the default constructor of Foo
leaves value
uninitialized. This is a flaw in my implementation of Foo
above (in my opinion), and except in special cases you will rarely want to do this.
这将进入免费存储(通常实现并调用堆),获得足够的内存来存储Foo,然后默认构造它。然后它返回Foo对象的地址,然后使用该地址初始化指针Foo* i。现在,请注意,Foo的默认构造函数没有初始化值。这是我在上面的Foo实现中的一个缺陷(在我看来),除了在特殊情况下,您很少希望这样做。
Annoyingly, integer (char
, int
, long
, unsigned char
, etc), floating point (double
or float
) literals, and pointer literals all share this property -- by default, they are not initialized to any value.
令人恼火的是,整数(char、int、long、unsigned char等)、浮点(double或float)常量和指针常量都共享此属性——默认情况下,它们不会初始化为任何值。
So you should make sure they are explicitly initialized. In the case of Foo
, adding a line:
因此,您应该确保它们是显式初始化的。对于Foo,加一行:
Foo():value() {}
is enough to do it.
这就足够了。
Foo* i = new Foo(0);
this goes to the free store (typically implemented and called the heap), gets ahold of enough memory to store a Foo
, then constructs it with the integer literal 0. It then returns the address of this Foo
object, which is then used to initialize the pointer Foo* i
.
这将进入免费存储(通常实现并调用堆),获得足够的内存来存储Foo,然后使用整数值0构造它。然后它返回这个Foo对象的地址,然后用来初始化指针Foo* i。
Now, memory in the free store generally stays reserved for your use once you ask for it until you get around to returning it, or your program shuts down. In order to return it, you call delete
on the same pointer, which both cases the object (Foo
in this case) to have its destructor called (Foo
has no destructor, so this is skipped), and then the memory is handed back to the free store to be used by a later call to new
.
现在,免费商店中的内存通常保留为您的使用,一旦您要求使用它,直到您开始返回它,或您的程序关闭。为了归还,你叫删除相同的指针,这两种情况下的对象(在这种情况下Foo)有其析构函数称为(Foo没有析构函数,这是跳过),然后回归*内存存储供以后的新电话。
Keeping track of this is a real pain, and a source of a whole bunch of errors, so you should avoid calling new
. There are many ways to avoid calling new
, including using std::vector
to manage blocks of memory, or using shared_ptr
and make_shared
to create objects on the heap which manage their own lifetime via a technique known as RAII, or using unique_ptr
when you want close control over the lifetime of a pointer (sadly, make_unique
doesn't exist).
跟踪这一点是一件非常痛苦的事情,而且会导致很多错误,所以应该避免调用new。避免调用新方法有很多,包括使用std::向量来管理内存块,或使用要和make_shared在堆上创建对象,通过技术称为RAII管理自己的生命周期,或者使用unique_ptr当你想关闭控制指针的生命周期(可悲的是,make_unique不存在)。
Now lets go further.
现在让我们走得更远。
Foo i = 0.0;
This fails to compile. I said that the constructor for Foo(double)
is explicit, and the above only chooses to call constructors that are non-explicit. On the other hand:
这无法编译。我说过Foo(double)的构造函数是显式的,上面的只选择调用非显式的构造函数。另一方面:
Foo i(0.0);
Foo i = Foo(0.0);
these both are willing to call explicit constructors, and work fine.
它们都愿意调用显式构造函数,并且工作良好。
Next, C++11 brings us uniform initialization. Instead of putting what you want to initialize something with in ()
, you put it in {}
-- a squiggly brace.
接下来,c++ 11为我们带来了统一的初始化。与其将想要初始化的东西放在in()中,不如将它放在{}——一个弯曲的括号中。
Foo i{0.0};
Foo i = {0};
etc. {}
has a few differences compared to ()
based syntax -- most importantly it avoids most vexing parse problems. Other differences include initializer list behavior, dealing with explicitly trivially constructing something (int x()
does not construct an int
named x
, but int x{}
does).
{}与基于()的语法相比有一些不同——最重要的是,它避免了最烦人的解析问题。其他的差异包括初始化器列表行为,显式地处理一些琐碎的构造(int x()并不构造一个名为x的int,而是int x{})。
Speaking of which, time to get back to your actual question.
说到这里,是时候回到你的实际问题了。
int
is different than my struct Foo
in a few ways.
int在一些方面与我的struct Foo不同。
First, it is not a class
or a struct
. So its behavior instead of being determined by some code you write, is instead described extensively by the standard. As it happens, C++ tries to have primitive types like int
behave a lot like a simple user defined type like Foo
, which is useful.
首先,它不是类或结构体。所以它的行为不是由你写的代码决定的,而是由标准广泛描述的。碰巧的是,c++尝试使用像int这样的原始类型,这与像Foo这样的简单用户定义类型非常相似,这很有用。
So while no "copy constructor" is called, and int
has no constructors nor destructors at all, int
almost exactly behaves "as if" there where such constructors.
因此,虽然没有调用“复制构造函数”,int也没有构造函数或析构函数,但是int几乎完全像这样的构造函数一样。
int i = 0;
creates the integer literal 0, then initializes int i
with it. The compiler may elide this, and simply create the integer int i
with the value 0 directly. For int
, there is no way to observe the difference directly.
创建整型文字0,然后用它初始化int i。编译器可以省略这个,直接创建值为0的整型int i。对于int,无法直接观察到差异。
int i(0);
is identical to int i = 0
, because int
has no non-explicit constructors. It is just a different syntax.
与int i = 0相同,因为int没有非显式构造函数。它只是一种不同的语法。
Now, there is the problem of the most vexing parse. If you typed
现在,有一个最烦人的解析问题。如果你输入
int i = int();
you'd get the same as int i = 0
, but if you typed
你会得到和int i = 0一样的结果,但是如果你输入
int i();
what would happen is that the compiler would say "that could be a function named i with takes zero arguments and returns int
", and for various annoying reasons prefers that interpretation to a default-initialized int
. So you get a forward-declared function named i
instead of an integer.
会发生的是编译器会说“这可能是一个名为i的函数,带0个参数并返回int”,出于各种恼人的原因,它更喜欢这种解释而不是默认初始化的int类型。
As mentioned earlier, the way to avoid this is to always use this syntax:
正如前面提到的,避免这种情况的方法是始终使用以下语法:
int i{};
in C++11 compilers.
在c++编译器。
Next, we have
接下来,我们有
int* p = new int;
which creates a default constructed (uninitialized) int
on the free store, and assigns a pointer to it to the variable int *p
. A copy has occurred, but it is a copy of a pointer, not the int
.
它在*存储上创建一个默认构造的(未初始化的)int,并向变量int *p分配一个指向它的指针。已经发生了一个副本,但它是一个指针的副本,而不是int。
int *p=new int(0);
is much the same, but the free store int
created has the value 0 instead of being uninitialized.
是一样的,但是创建的*存储int具有值0而不是未初始化。
In both these cases, you are responsible for calling delete
once and only once on the value returned by new
. Failure to do so is known as a memory leak. Using the pointer value after you have done so results in undefined behavior, and typically memory corruption. You almost certainly won't be warned by the program that what you did is dangerous, but your program can now do utterly random things that make no sense and still be a valid C++ program. Aligning each new
with exactly one delete
, and making sure that nobody uses pointers after the delete
, and calling delete
as early as possible, is an annoying enough program that entire categories of programming languages have been developed whose main selling feature is that they free developers from having to deal with it.
在这两种情况下,您都要对new返回的值调用一次且仅调用一次delete。不这样做被称为内存泄漏。在这样做之后使用指针值会导致未定义的行为,通常会导致内存损坏。你几乎肯定不会被程序警告你所做的是危险的,但是你的程序现在可以做一些毫无意义的随机的事情,并且仍然是一个有效的c++程序。调整每一个新的一个删除,确保没有人使用指针删除后,尽早和调用删除,足够一个恼人的程序,整个类别的编程语言开发的主要销售特性是他们免费开发人员不必处理它。
So avoid calling new
.
所以避免调用新的。
Oh, and because this isn't long enough, note that my use of the "most vexing parse" above is not quite right. The "most vexing parse" is actually:
哦,而且因为这还不够长,请注意我使用上面的“最烦人的解析”不是很正确。“最伤脑筋的解析”实际上是:
int x(int());
rather than
而不是
int x();
because the first could be either a constructor call or a function, while the second cannot be a constructor call because the standard doesn't allow it.
因为第一个可以是构造函数调用或函数,而第二个不能是构造函数调用,因为标准不允许这样做。
However, I and most other people find the parsing rules that make int x();
, so call it the penultimate vexing parse, and you won't be far wrong. It still doesn't do what you would naively think it should do (create a default constructed x
), so it is plenty vexing.
但是,我和大多数其他人都发现了构成int x()的解析规则,因此将其称为倒数第二烦人的解析,您不会错得太远。它仍然没有做你会天真地认为它应该做的事情(创建一个默认构造的x),所以这是非常麻烦的。
#2
2
int i=0;
int i(0);
these are the same, with two different initialization syntaxes (C-like the first, constructor-style the second); in line of principle they are slightly different when dealing with classes (the first one implies a - potentially elided - call to a copy constructor, the second doesn't), but for int
s they are effectively the same.
它们是相同的,具有两个不同的初始化语法(第一个是c,第二个是构造函数);原则上,它们在处理类时略有不同(第一个表示对复制构造函数的调用(可能省略),第二个则没有),但对于int来说,它们实际上是相同的。
int *p=new int;
int *p=new int(0);
In the first one the int
is not initialized (it will have whatever value happens to be at that memory location); in the second case, the int
is initialized to 0.
在第一个中,int没有初始化(它将具有在该内存位置上发生的任何值);在第二种情况下,int值被初始化为0。
But most importantly, these are two completely different beasts in respect to the first ones. You are not declaring an automatic variables of type int
, but pointers to int
, which point to two dynamically allocated int
s.
但最重要的是,这是两种完全不同的野兽。您不是在声明int类型的自动变量,而是指向int的指针,它指向两个动态分配的int类型。
The difference is deep: with int i=0
the memory is managed automatically (it has automatic storage duration), and the variable is destroyed when it goes out of scope; with new
you allocate memory from the freestore (the so-called heap), which doesn't have an automatic deallocation method - you have to free it explicitly (with delete
, although in modern C++ smart pointers are normally used to automatically manage the lifetime of dynamic objects).
不同之处在于:当int i=0时,内存是自动管理的(它有自动的存储时间),当变量超出范围时则被销毁;使用new,您可以从独立内核(所谓的堆)中分配内存,它没有自动的释放方法——您必须显式释放内存(使用delete,尽管在现代c++智能指针通常用于自动管理动态对象的生命周期)。
new
is normally used exactly for the cases of when automatic storage duration isn't a good choice (e.g. you want those int
s to outlive the current scope, or be shared between several objects or whatever) or when you are allocating stuff that is too big to stay in a local variable (in typical implementation local variables go on the stack, which is limited in size; still, for two int
s that's not a valid concern).
新时通常使用完全的情况下自动存储时间不是一个好的选择(例如你希望这些整数比当前的范围,或多个对象之间共享)或分配的东西太大了,当你呆在一个本地变量(在典型实现局部变量在堆栈上,规模是有限的;尽管如此,对于两个ints来说,这并不是一个有效的关注)。
For "regular", local int
variables that have to "die" with the current scope new
usually isn't a good idea.
对于“规则的”,必须使用当前的范围“die”的局部int变量通常不是一个好主意。
Still, for more information about dynamic allocation you should check your C++ book.
不过,要了解更多关于动态分配的信息,您应该查看c++书籍。
#3
2
in C and early C++ you could only use int i=0;
在C和早期c++中,只能使用int i=0;
The int i(0);
pattern is the same as a constructor for a general type
int(0);模式与通用类型的构造函数相同
T i(0);
So it was added as an alternative to int i=0;
which does not look like a general constructor pattern. This is useful when templates are used. So the template can use int as well as classes.
所以它被作为int i=0的替代;它看起来不像通用构造函数模式。这在使用模板时非常有用。因此模板可以使用int和类。
#4
-1
new
implies heap memory allocation (which can leak), so no, you don't want to be doing it all the time.
new意味着堆内存分配(可能会泄漏),所以不,您不希望一直这样做。
int i=0;
and int i(0);
are equivalent, but depending on the implementation the first may use an assignment operator while the second may be constructed with a value. This can let the compiler optimize for the target architecture. In the case of a class, the assignment method is probably slower since it will create a class (usually with default values) and then it will go through an assignment and wipe out all those default values it just spent time assigning.
int i = 0;我int(0);是等价的,但是根据实现,第一个可以使用赋值操作符,而第二个可以用一个值构造。这可以让编译器优化目标体系结构。在类的情况下,赋值方法可能比较慢,因为它将创建一个类(通常使用默认值),然后它将执行赋值,并删除它刚刚花时间赋值的所有默认值。
Someone may chime in and reference the language spec for a more accurate answer.
有人可能会插话,并参考语言规范以获得更准确的答案。
#1
5
I'm going to answer a slightly different question first.
我先回答一个稍微不同的问题。
Suppose you have a class
or struct
(they are pretty much the same) that looks like this:
假设您有一个类或结构(它们几乎是相同的):
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
};
now, this is much like an int
, but there are a few differences.
现在,这很像int,但是有一些区别。
Foo i = 0;
the above creates an int
literal, then constructs Foo i
with it using the Foo(int v)
constructor.
上面创建了一个int文字,然后使用Foo(int v)构造函数构造Foo i。
Foo i(0);
the above creates an int
literal, then constructs Foo i
with it using the Foo(int v)
constructor. Note that I just repeated myself.
上面创建了一个int文字,然后使用Foo(int v)构造函数构造Foo i。注意,我只是重复了一遍。
Foo i = Foo(0);
the above creates an int
literal, then constructs Foo i
with it using the Foo(int v)
constructor, then copy-constructs Foo i
from it. However, the standard allows the compiler to "elide" (skip) the copy constructor, and instead just construct Foo i
directly from the int
literal 0
.
上面创建了一个int文字,然后使用Foo(int v)构造函数构造Foo i,然后从它复制构造Foo i。但是,该标准允许编译器“省略”(跳过)复制构造函数,而是直接从int文字0构造Foo i。
Foo* i = new Foo;
this goes to the free store (typically implemented and called the heap), gets ahold of enough memory to store a Foo
, then default constructs it. It then returns the address of this Foo
object, which is then used to initialize the pointer Foo* i
. Now, note that the default constructor of Foo
leaves value
uninitialized. This is a flaw in my implementation of Foo
above (in my opinion), and except in special cases you will rarely want to do this.
这将进入免费存储(通常实现并调用堆),获得足够的内存来存储Foo,然后默认构造它。然后它返回Foo对象的地址,然后使用该地址初始化指针Foo* i。现在,请注意,Foo的默认构造函数没有初始化值。这是我在上面的Foo实现中的一个缺陷(在我看来),除了在特殊情况下,您很少希望这样做。
Annoyingly, integer (char
, int
, long
, unsigned char
, etc), floating point (double
or float
) literals, and pointer literals all share this property -- by default, they are not initialized to any value.
令人恼火的是,整数(char、int、long、unsigned char等)、浮点(double或float)常量和指针常量都共享此属性——默认情况下,它们不会初始化为任何值。
So you should make sure they are explicitly initialized. In the case of Foo
, adding a line:
因此,您应该确保它们是显式初始化的。对于Foo,加一行:
Foo():value() {}
is enough to do it.
这就足够了。
Foo* i = new Foo(0);
this goes to the free store (typically implemented and called the heap), gets ahold of enough memory to store a Foo
, then constructs it with the integer literal 0. It then returns the address of this Foo
object, which is then used to initialize the pointer Foo* i
.
这将进入免费存储(通常实现并调用堆),获得足够的内存来存储Foo,然后使用整数值0构造它。然后它返回这个Foo对象的地址,然后用来初始化指针Foo* i。
Now, memory in the free store generally stays reserved for your use once you ask for it until you get around to returning it, or your program shuts down. In order to return it, you call delete
on the same pointer, which both cases the object (Foo
in this case) to have its destructor called (Foo
has no destructor, so this is skipped), and then the memory is handed back to the free store to be used by a later call to new
.
现在,免费商店中的内存通常保留为您的使用,一旦您要求使用它,直到您开始返回它,或您的程序关闭。为了归还,你叫删除相同的指针,这两种情况下的对象(在这种情况下Foo)有其析构函数称为(Foo没有析构函数,这是跳过),然后回归*内存存储供以后的新电话。
Keeping track of this is a real pain, and a source of a whole bunch of errors, so you should avoid calling new
. There are many ways to avoid calling new
, including using std::vector
to manage blocks of memory, or using shared_ptr
and make_shared
to create objects on the heap which manage their own lifetime via a technique known as RAII, or using unique_ptr
when you want close control over the lifetime of a pointer (sadly, make_unique
doesn't exist).
跟踪这一点是一件非常痛苦的事情,而且会导致很多错误,所以应该避免调用new。避免调用新方法有很多,包括使用std::向量来管理内存块,或使用要和make_shared在堆上创建对象,通过技术称为RAII管理自己的生命周期,或者使用unique_ptr当你想关闭控制指针的生命周期(可悲的是,make_unique不存在)。
Now lets go further.
现在让我们走得更远。
Foo i = 0.0;
This fails to compile. I said that the constructor for Foo(double)
is explicit, and the above only chooses to call constructors that are non-explicit. On the other hand:
这无法编译。我说过Foo(double)的构造函数是显式的,上面的只选择调用非显式的构造函数。另一方面:
Foo i(0.0);
Foo i = Foo(0.0);
these both are willing to call explicit constructors, and work fine.
它们都愿意调用显式构造函数,并且工作良好。
Next, C++11 brings us uniform initialization. Instead of putting what you want to initialize something with in ()
, you put it in {}
-- a squiggly brace.
接下来,c++ 11为我们带来了统一的初始化。与其将想要初始化的东西放在in()中,不如将它放在{}——一个弯曲的括号中。
Foo i{0.0};
Foo i = {0};
etc. {}
has a few differences compared to ()
based syntax -- most importantly it avoids most vexing parse problems. Other differences include initializer list behavior, dealing with explicitly trivially constructing something (int x()
does not construct an int
named x
, but int x{}
does).
{}与基于()的语法相比有一些不同——最重要的是,它避免了最烦人的解析问题。其他的差异包括初始化器列表行为,显式地处理一些琐碎的构造(int x()并不构造一个名为x的int,而是int x{})。
Speaking of which, time to get back to your actual question.
说到这里,是时候回到你的实际问题了。
int
is different than my struct Foo
in a few ways.
int在一些方面与我的struct Foo不同。
First, it is not a class
or a struct
. So its behavior instead of being determined by some code you write, is instead described extensively by the standard. As it happens, C++ tries to have primitive types like int
behave a lot like a simple user defined type like Foo
, which is useful.
首先,它不是类或结构体。所以它的行为不是由你写的代码决定的,而是由标准广泛描述的。碰巧的是,c++尝试使用像int这样的原始类型,这与像Foo这样的简单用户定义类型非常相似,这很有用。
So while no "copy constructor" is called, and int
has no constructors nor destructors at all, int
almost exactly behaves "as if" there where such constructors.
因此,虽然没有调用“复制构造函数”,int也没有构造函数或析构函数,但是int几乎完全像这样的构造函数一样。
int i = 0;
creates the integer literal 0, then initializes int i
with it. The compiler may elide this, and simply create the integer int i
with the value 0 directly. For int
, there is no way to observe the difference directly.
创建整型文字0,然后用它初始化int i。编译器可以省略这个,直接创建值为0的整型int i。对于int,无法直接观察到差异。
int i(0);
is identical to int i = 0
, because int
has no non-explicit constructors. It is just a different syntax.
与int i = 0相同,因为int没有非显式构造函数。它只是一种不同的语法。
Now, there is the problem of the most vexing parse. If you typed
现在,有一个最烦人的解析问题。如果你输入
int i = int();
you'd get the same as int i = 0
, but if you typed
你会得到和int i = 0一样的结果,但是如果你输入
int i();
what would happen is that the compiler would say "that could be a function named i with takes zero arguments and returns int
", and for various annoying reasons prefers that interpretation to a default-initialized int
. So you get a forward-declared function named i
instead of an integer.
会发生的是编译器会说“这可能是一个名为i的函数,带0个参数并返回int”,出于各种恼人的原因,它更喜欢这种解释而不是默认初始化的int类型。
As mentioned earlier, the way to avoid this is to always use this syntax:
正如前面提到的,避免这种情况的方法是始终使用以下语法:
int i{};
in C++11 compilers.
在c++编译器。
Next, we have
接下来,我们有
int* p = new int;
which creates a default constructed (uninitialized) int
on the free store, and assigns a pointer to it to the variable int *p
. A copy has occurred, but it is a copy of a pointer, not the int
.
它在*存储上创建一个默认构造的(未初始化的)int,并向变量int *p分配一个指向它的指针。已经发生了一个副本,但它是一个指针的副本,而不是int。
int *p=new int(0);
is much the same, but the free store int
created has the value 0 instead of being uninitialized.
是一样的,但是创建的*存储int具有值0而不是未初始化。
In both these cases, you are responsible for calling delete
once and only once on the value returned by new
. Failure to do so is known as a memory leak. Using the pointer value after you have done so results in undefined behavior, and typically memory corruption. You almost certainly won't be warned by the program that what you did is dangerous, but your program can now do utterly random things that make no sense and still be a valid C++ program. Aligning each new
with exactly one delete
, and making sure that nobody uses pointers after the delete
, and calling delete
as early as possible, is an annoying enough program that entire categories of programming languages have been developed whose main selling feature is that they free developers from having to deal with it.
在这两种情况下,您都要对new返回的值调用一次且仅调用一次delete。不这样做被称为内存泄漏。在这样做之后使用指针值会导致未定义的行为,通常会导致内存损坏。你几乎肯定不会被程序警告你所做的是危险的,但是你的程序现在可以做一些毫无意义的随机的事情,并且仍然是一个有效的c++程序。调整每一个新的一个删除,确保没有人使用指针删除后,尽早和调用删除,足够一个恼人的程序,整个类别的编程语言开发的主要销售特性是他们免费开发人员不必处理它。
So avoid calling new
.
所以避免调用新的。
Oh, and because this isn't long enough, note that my use of the "most vexing parse" above is not quite right. The "most vexing parse" is actually:
哦,而且因为这还不够长,请注意我使用上面的“最烦人的解析”不是很正确。“最伤脑筋的解析”实际上是:
int x(int());
rather than
而不是
int x();
because the first could be either a constructor call or a function, while the second cannot be a constructor call because the standard doesn't allow it.
因为第一个可以是构造函数调用或函数,而第二个不能是构造函数调用,因为标准不允许这样做。
However, I and most other people find the parsing rules that make int x();
, so call it the penultimate vexing parse, and you won't be far wrong. It still doesn't do what you would naively think it should do (create a default constructed x
), so it is plenty vexing.
但是,我和大多数其他人都发现了构成int x()的解析规则,因此将其称为倒数第二烦人的解析,您不会错得太远。它仍然没有做你会天真地认为它应该做的事情(创建一个默认构造的x),所以这是非常麻烦的。
#2
2
int i=0;
int i(0);
these are the same, with two different initialization syntaxes (C-like the first, constructor-style the second); in line of principle they are slightly different when dealing with classes (the first one implies a - potentially elided - call to a copy constructor, the second doesn't), but for int
s they are effectively the same.
它们是相同的,具有两个不同的初始化语法(第一个是c,第二个是构造函数);原则上,它们在处理类时略有不同(第一个表示对复制构造函数的调用(可能省略),第二个则没有),但对于int来说,它们实际上是相同的。
int *p=new int;
int *p=new int(0);
In the first one the int
is not initialized (it will have whatever value happens to be at that memory location); in the second case, the int
is initialized to 0.
在第一个中,int没有初始化(它将具有在该内存位置上发生的任何值);在第二种情况下,int值被初始化为0。
But most importantly, these are two completely different beasts in respect to the first ones. You are not declaring an automatic variables of type int
, but pointers to int
, which point to two dynamically allocated int
s.
但最重要的是,这是两种完全不同的野兽。您不是在声明int类型的自动变量,而是指向int的指针,它指向两个动态分配的int类型。
The difference is deep: with int i=0
the memory is managed automatically (it has automatic storage duration), and the variable is destroyed when it goes out of scope; with new
you allocate memory from the freestore (the so-called heap), which doesn't have an automatic deallocation method - you have to free it explicitly (with delete
, although in modern C++ smart pointers are normally used to automatically manage the lifetime of dynamic objects).
不同之处在于:当int i=0时,内存是自动管理的(它有自动的存储时间),当变量超出范围时则被销毁;使用new,您可以从独立内核(所谓的堆)中分配内存,它没有自动的释放方法——您必须显式释放内存(使用delete,尽管在现代c++智能指针通常用于自动管理动态对象的生命周期)。
new
is normally used exactly for the cases of when automatic storage duration isn't a good choice (e.g. you want those int
s to outlive the current scope, or be shared between several objects or whatever) or when you are allocating stuff that is too big to stay in a local variable (in typical implementation local variables go on the stack, which is limited in size; still, for two int
s that's not a valid concern).
新时通常使用完全的情况下自动存储时间不是一个好的选择(例如你希望这些整数比当前的范围,或多个对象之间共享)或分配的东西太大了,当你呆在一个本地变量(在典型实现局部变量在堆栈上,规模是有限的;尽管如此,对于两个ints来说,这并不是一个有效的关注)。
For "regular", local int
variables that have to "die" with the current scope new
usually isn't a good idea.
对于“规则的”,必须使用当前的范围“die”的局部int变量通常不是一个好主意。
Still, for more information about dynamic allocation you should check your C++ book.
不过,要了解更多关于动态分配的信息,您应该查看c++书籍。
#3
2
in C and early C++ you could only use int i=0;
在C和早期c++中,只能使用int i=0;
The int i(0);
pattern is the same as a constructor for a general type
int(0);模式与通用类型的构造函数相同
T i(0);
So it was added as an alternative to int i=0;
which does not look like a general constructor pattern. This is useful when templates are used. So the template can use int as well as classes.
所以它被作为int i=0的替代;它看起来不像通用构造函数模式。这在使用模板时非常有用。因此模板可以使用int和类。
#4
-1
new
implies heap memory allocation (which can leak), so no, you don't want to be doing it all the time.
new意味着堆内存分配(可能会泄漏),所以不,您不希望一直这样做。
int i=0;
and int i(0);
are equivalent, but depending on the implementation the first may use an assignment operator while the second may be constructed with a value. This can let the compiler optimize for the target architecture. In the case of a class, the assignment method is probably slower since it will create a class (usually with default values) and then it will go through an assignment and wipe out all those default values it just spent time assigning.
int i = 0;我int(0);是等价的,但是根据实现,第一个可以使用赋值操作符,而第二个可以用一个值构造。这可以让编译器优化目标体系结构。在类的情况下,赋值方法可能比较慢,因为它将创建一个类(通常使用默认值),然后它将执行赋值,并删除它刚刚花时间赋值的所有默认值。
Someone may chime in and reference the language spec for a more accurate answer.
有人可能会插话,并参考语言规范以获得更准确的答案。