13

我正在阅读 C++ 的教程,但它实际上并没有给我两者之间的区别(除了语法)。这是教程中的引用。

您还可以在声明时为变量赋值。当我们使用赋值运算符(等号)为变量赋值时,它被称为显式赋值:

int nValue = 5; // explicit assignment

您还可以使用隐式赋值为变量赋值:

int nValue(5); // implicit assignment

尽管隐式赋值看起来很像函数调用,但编译器会跟踪哪些名称是变量,哪些是函数,以便正确解析它们。

有区别吗?一个比另一个更受欢迎吗?

4

3 回答 3

13

第一个是原始类型的首选,例如int; 第二个是具有构造函数的类型,因为它使构造函数调用显式。

例如,如果您定义了class Foo可以从单个 构造的 a int,那么

Foo x(5);

优先于

Foo x = 5;

(无论如何,当传递多个参数时,您都需要前一种语法,除非您使用Foo x = Foo(5, "hello");明显丑陋且看起来operator=正在被调用的语法。)

于 2011-07-19T18:06:42.560 回答
6

对于原始类型,两者都是等价的,但对于用户定义的类类型,则存在差异。在这两种情况下,执行的代码都是相同的(在执行基本优化之后),但是如果我们初始化的元素不是我们正在构造的类型,则对类型的要求会有所不同。

复制初始化( T t = u;) 等效于从T已隐式转换为u的临时类型的复制构造t。另一方面,直接初始化等效于直接调用适当的构造函数。

虽然在大多数情况下没有区别,但如果声明了接受 的构造函数uexplicit复制构造函数不可访问,则复制初始化将失败:

struct A {
   explicit A( int ) {}
};
struct B {
   B( int ) {}
private:
   B( B const & );
};
int main() {
   A a(1);      // ok
   B b(1);      // ok
// A a2 = 1;    // error: cannot convert from int to A
// B b2 = 1;    // error: B( B const & ) is not accessible
}

对于某些历史背景,最初的原始类型必须使用copy-initialization 进行初始化。当 *initializer-list*s 被添加到语言中以初始化类的成员属性时,决定原始类型应该使用与类相同的语法进行初始化,以保持初始化列表中的语法统一和简单。同时允许通过复制初始化来初始化类,使用户定义的类型更接近原始类型。两种初始化格式的区别自然而然:int a = 5.0;被处理为从5.0to的转换int,然后aint. 用户定义的类型也是如此:T u = v;被处理为从vto的转换T,然后u从该转换值复制构造。

于 2011-07-19T19:32:41.637 回答
3

当您声明一个变量并对其进行初始化时,它们在该上下文中的功能相同。我通常将两者称为:

int nValue = 5; // assignment syntax

int nValue(5); // construction syntax

对于基本类型,我更喜欢赋值而不是构造,因为它更自然,特别是对于那些用其他语言编程的人。

对于类类型,我更喜欢构造语法,因为它避免了构造函数的存在。

于 2011-07-19T18:07:08.877 回答