初始化:括号与等号[复制]

时间:2020-12-14 16:26:45

Possible Duplicate:
Is there a difference in C++ between copy initialization and assignment initialization?

可能的重复:在c++中,拷贝初始化和赋值初始化有区别吗?

What's the difference between

有什么区别

T a(b);

and

T a = b;

and

T a = T(b);

?

吗?

4 个解决方案

#1


23  

T a( b );

is direct initialization, unless it parses as a function declaration, in which case it's a function declaration.

是直接初始化,除非它是一个函数声明,在这种情况下,它是一个函数声明。

T a = b;

is copy initialization, which means that it works as if a temporary object is constructed on the right hand side, and that a is then copy constructed or, in C++11 and later, possibly move constructed, from that temporary.

是copy初始化,这意味着它工作起来就好像一个临时对象被构造在右手边,然后a被构造为copy,或者,在c++ 11中,之后,可能会从临时对象中移动构造。

The compiler is free to elide (remove) the temporary+copying/moving whenever it can, but a copy or move constructor, whichever would be logically used, must still be accessible and not explicit.

编译器可以*地省略(删除)临时+复制/移动,但是一个复制或移动构造函数(无论逻辑上使用哪个构造函数)仍然必须是可访问的,且不显式的。

For example, in C++03 you cannot copy-initialize a std::ostringstream, because it doesn't have a copy constructor. In C++11 you can copy-initialize an ostringstream if the initializer is a temporary, which then results in a logical move construction (which however will usually be elided, optimized away). For example, this copy initialization declaration,

例如,在c++ 03中,您不能复制-初始化std::ostringstream,因为它没有复制构造函数。在c++ 11中,如果初始化器是临时的,就可以复制一个ostringstream,这样就会产生一个逻辑的移动构造(不过通常会被省略,优化掉)。例如,这个复制初始化声明,

ostringstream s = ostringstream( "blah" );

… doesn't compile as C++03, because in C++03 the copy initialization invokes the class' copy constructor, which doesn't exist. It does however compile as C++11, because in C++11 the copy initialization invokes the move constructor. And while (to maintain its illusion of being a stream) a std::ostringstream can't be directly copied, it can be moved.

因为在c++ 03中,复制初始化调用类的复制构造函数,而这个构造函数并不存在。但是,它确实是作为c++ 11编译的,因为在c++ 11中,复制初始化调用了move构造函数。而(为了保持它作为流的错觉)std::ostringstream不能被直接复制,它可以被移动。

Another such difference: in C++03 only the copy initialization syntax supports curly braces initializer, which in C++03 you can use when T is an aggregate type such as a raw array. In C++11 the curly braces notation has been extended and generalized as a uniform initialization syntax, so it can be used also with direct initialization. And so the following direct initialization declaration,

另一种差异是:在c++ 03中,只有复制初始化语法支持花括号初始化,在c++ 03中,当T是集合类型(如原始数组)时,可以使用它。在c++ 11中,花括号表示法已经作为统一的初始化语法进行了扩展和推广,因此它也可以用于直接初始化。下面的直接初始化声明,

int v[]{ 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };

… does not compile as C++03, but does compile as C++11 and later.

…不是作为c++ 03编译的,而是作为c++ 11编译的。

The = copy initialization syntax is the original initialization syntax from C.

复制初始化语法是来自C的初始化语法。

And in C++11 and later, due to move semantics, it can be used in a much wider range of cases than in C++03, such as with a std::ostringstream.

在c++ 11和以后的c++ 11中,由于移动语义,它可以在比c++ 03中更广泛的情况下使用,例如在std::ostringstream中。

#2


17  

T a(b);

Calls a constructor of a that accepts b. (If b is of the same type, then the copy constructor is called).

调用接受b的a的构造函数(如果b的类型相同,则调用copy构造函数)。

T a = b;

a temporary object of type T is created to be constructed by b. Then the copy constructor is called(= is not an assignment in this case and the next case!).

类型T的临时对象是由b创建的,然后调用复制构造函数(=不是这个例子中的赋值和下一个例子!)

T a = T(b);

Same as above! except that we explicitly constructed a temporary object.

同上!除了我们显式地构造了一个临时对象。

Note that the standard allows total elimination of temporary copies in the second and third case. Also, if b is not of type T, then in the first case T doesn't have to have a copy constructor. In the second and third cases, even though the implementation is free to optimize the whole thing, it still requires an accessible copy constructor. IIRC the standard calls this: copy elision.

注意,该标准允许在第二和第三种情况下完全消除临时副本。而且,如果b不是T类型,那么在第一种情况下,T不需要一个复制构造函数。在第二和第三种情况下,即使实现可以*地优化整个过程,它仍然需要一个可访问的复制构造函数。IIRC标准称之为:复制省略。

#3


0  

They are all constructor calls - the = sign is just syntactic sugar. Exactly which constructors get called is to a certain extent up to the compiler.

它们都是构造函数调用- =符号只是语法糖。调用哪个构造函数在一定程度上取决于编译器。

#4


-3  

The = operator will invoke the default copy constructor unless the = operator is overloaded I believe... this would make a shallow copy; assigning the same member values to the first object as the right-hand operator

=操作符将调用默认的复制构造函数,除非=操作符重载…这将是一个浅拷贝;将与右边操作符相同的成员值分配给第一个对象

#1


23  

T a( b );

is direct initialization, unless it parses as a function declaration, in which case it's a function declaration.

是直接初始化,除非它是一个函数声明,在这种情况下,它是一个函数声明。

T a = b;

is copy initialization, which means that it works as if a temporary object is constructed on the right hand side, and that a is then copy constructed or, in C++11 and later, possibly move constructed, from that temporary.

是copy初始化,这意味着它工作起来就好像一个临时对象被构造在右手边,然后a被构造为copy,或者,在c++ 11中,之后,可能会从临时对象中移动构造。

The compiler is free to elide (remove) the temporary+copying/moving whenever it can, but a copy or move constructor, whichever would be logically used, must still be accessible and not explicit.

编译器可以*地省略(删除)临时+复制/移动,但是一个复制或移动构造函数(无论逻辑上使用哪个构造函数)仍然必须是可访问的,且不显式的。

For example, in C++03 you cannot copy-initialize a std::ostringstream, because it doesn't have a copy constructor. In C++11 you can copy-initialize an ostringstream if the initializer is a temporary, which then results in a logical move construction (which however will usually be elided, optimized away). For example, this copy initialization declaration,

例如,在c++ 03中,您不能复制-初始化std::ostringstream,因为它没有复制构造函数。在c++ 11中,如果初始化器是临时的,就可以复制一个ostringstream,这样就会产生一个逻辑的移动构造(不过通常会被省略,优化掉)。例如,这个复制初始化声明,

ostringstream s = ostringstream( "blah" );

… doesn't compile as C++03, because in C++03 the copy initialization invokes the class' copy constructor, which doesn't exist. It does however compile as C++11, because in C++11 the copy initialization invokes the move constructor. And while (to maintain its illusion of being a stream) a std::ostringstream can't be directly copied, it can be moved.

因为在c++ 03中,复制初始化调用类的复制构造函数,而这个构造函数并不存在。但是,它确实是作为c++ 11编译的,因为在c++ 11中,复制初始化调用了move构造函数。而(为了保持它作为流的错觉)std::ostringstream不能被直接复制,它可以被移动。

Another such difference: in C++03 only the copy initialization syntax supports curly braces initializer, which in C++03 you can use when T is an aggregate type such as a raw array. In C++11 the curly braces notation has been extended and generalized as a uniform initialization syntax, so it can be used also with direct initialization. And so the following direct initialization declaration,

另一种差异是:在c++ 03中,只有复制初始化语法支持花括号初始化,在c++ 03中,当T是集合类型(如原始数组)时,可以使用它。在c++ 11中,花括号表示法已经作为统一的初始化语法进行了扩展和推广,因此它也可以用于直接初始化。下面的直接初始化声明,

int v[]{ 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };

… does not compile as C++03, but does compile as C++11 and later.

…不是作为c++ 03编译的,而是作为c++ 11编译的。

The = copy initialization syntax is the original initialization syntax from C.

复制初始化语法是来自C的初始化语法。

And in C++11 and later, due to move semantics, it can be used in a much wider range of cases than in C++03, such as with a std::ostringstream.

在c++ 11和以后的c++ 11中,由于移动语义,它可以在比c++ 03中更广泛的情况下使用,例如在std::ostringstream中。

#2


17  

T a(b);

Calls a constructor of a that accepts b. (If b is of the same type, then the copy constructor is called).

调用接受b的a的构造函数(如果b的类型相同,则调用copy构造函数)。

T a = b;

a temporary object of type T is created to be constructed by b. Then the copy constructor is called(= is not an assignment in this case and the next case!).

类型T的临时对象是由b创建的,然后调用复制构造函数(=不是这个例子中的赋值和下一个例子!)

T a = T(b);

Same as above! except that we explicitly constructed a temporary object.

同上!除了我们显式地构造了一个临时对象。

Note that the standard allows total elimination of temporary copies in the second and third case. Also, if b is not of type T, then in the first case T doesn't have to have a copy constructor. In the second and third cases, even though the implementation is free to optimize the whole thing, it still requires an accessible copy constructor. IIRC the standard calls this: copy elision.

注意,该标准允许在第二和第三种情况下完全消除临时副本。而且,如果b不是T类型,那么在第一种情况下,T不需要一个复制构造函数。在第二和第三种情况下,即使实现可以*地优化整个过程,它仍然需要一个可访问的复制构造函数。IIRC标准称之为:复制省略。

#3


0  

They are all constructor calls - the = sign is just syntactic sugar. Exactly which constructors get called is to a certain extent up to the compiler.

它们都是构造函数调用- =符号只是语法糖。调用哪个构造函数在一定程度上取决于编译器。

#4


-3  

The = operator will invoke the default copy constructor unless the = operator is overloaded I believe... this would make a shallow copy; assigning the same member values to the first object as the right-hand operator

=操作符将调用默认的复制构造函数,除非=操作符重载…这将是一个浅拷贝;将与右边操作符相同的成员值分配给第一个对象