2011-07-19 51 views
10

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

您也可以在声明时为变量赋值。当我们 赋值使用赋值运算符的变量(等于 号),它被称为一个明确的赋值:

int nValue(5); // implicit assignment 

int nValue = 5; // explicit assignment 

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

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

+5

这不是一个声明,它的定义。沟教程和[阅读一本体面的书](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)。用C++进行思考是免费的,可以从作者的页面获得。 –

+3

@Cat Plus Plus:这是一个定义,但这并不意味着它不是一个声明。 –

+1

@JamesMcNellis:它应该是一个教程,调用定义声明无助于摆脱两者之间的混淆。也许我今天只是胡思乱想而已。 :+ –

回答

10

第一个是基本类型,如int;第二种是具有构造函数的类型,因为它使构造函数调用显式化。

例如,如果您已经定义了一个class Foo,可以从一个单一的int构造,然后

Foo x(5); 

优于

Foo x = 5; 

(你需要前者的语法比反正多的时候一个参数被传递,除非你使用的是Foo x = Foo(5, "hello");,这很简单,看起来像operator=被调用。)

+4

值得一提的是,使用构造语法时,您需要小心最棘手的分析。 –

+4

另请注意,如果'Foo :: Foo(int)'没有标记为'explicit',则'Foo x = 5'才会起作用。 – Vitus

+0

...(继续@Vitus评论)和'Foo'拷贝构造函数是可访问的。 –

1

当你声明一个变量并对其进行初始化时,它们在功能上与上下文相同。我通常是指两个为:

int nValue = 5; // assignment syntax 

int nValue(5); // construction syntax 

基本类型,我更喜欢建设任务,因为它是更加自然,尤其是对于那些谁在其他语言编程。

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

+1

标准(N3242)调用语法'T x = a' *复制初始化*和'T x(a)'*直接初始化*。两者都是调用构造函数'T :: T(a)'的有效方式。 –

5

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

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

虽然在大多数情况下,不会有任何区别,如果采取u构造函数声明explicit或者如果拷贝构造无法访问,然后复制初始化将失败:

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 
} 

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