显式赋值vs隐式赋值
Explicit Assignment vs Implicit Assignment
我正在阅读c++教程,但它实际上并没有给我两者之间的区别(除了语法)。以下是教程中的一段话。
您还可以在声明时为变量赋值。当我们使用赋值操作符(等号)为变量赋值符号),它被称为显式赋值:
int nValue = 5; // explicit assignment
你也可以使用隐式赋值给变量赋值:
int nValue(5); // implicit assignment
尽管隐式赋值看起来很像函数调用编译器跟踪哪些名称是变量,哪些是变量函数,以便它们可以正确地解析。
有区别吗?哪个更受欢迎?
对于基本类型,如int
;第二种使用具有构造函数的类型,因为它使构造函数调用显式。
。,如果您定义了可以由单个int
构造的class Foo
,则
Foo x(5);
优于
Foo x = 5;
(无论如何,当传递多个参数时,您需要前一种语法,除非您使用Foo x = Foo(5, "hello");
,这很难看,看起来像正在调用operator=
。)
对于基本类型两者都是等效的,只有对于用户定义的类类型才有区别。在这两种情况下,执行的代码将是相同的(在执行基本优化之后),但是如果我们初始化的元素不是我们正在构造的类型,则对类型的要求是不同的。
复制初始化 (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
}
在某些历史背景下,最初的基本类型必须用copy-initialization初始化。当*initializer-list*s被添加到语言中用于初始化类的成员属性时,决定基本类型应该使用与类相同的语法进行初始化,以保持初始化列表中的语法统一和简单。同时,允许通过复制初始化对类进行初始化,使得用户定义的类型更接近基本类型。两种初始化格式的差异是很自然的:int a = 5.0;
被处理为从5.0
到int
的转换,然后从int
初始化a
。用户定义的类型也是如此:将T u = v;
处理为从v
到T
的转换,然后从转换后的值复制u
的构造。
在声明变量和初始化变量时,它们在该上下文中在功能上是相同的。我通常把这两者称为:
int nValue = 5; // assignment syntax
和
int nValue(5); // construction syntax
对于基本类型,我更喜欢赋值而不是构造,因为它更自然,特别是对于那些用其他语言编程的人。
对于类类型,我更喜欢构造语法,因为它避免了构造函数的存在。
- 为"adjacent"变量赋值时出现问题
- C++中的赋值发生,尽管右侧出现异常
- 用C++中的sscanf赋值
- 为std::string的某个索引赋值
- 重载Singly Linked List中的赋值运算符
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- gtest_使用setargpointee在函数中赋值
- 非常量变量只读位置的赋值
- 使用赋值运算符重载从类中返回jobject
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 可以错误地使用赋值运算符而不是比较运算符的地方,= Vs ==
- C++空映射赋值:等于vs插入
- 绕过自动生成的赋值运算符(VS 错误?
- 'for' 循环中的 'int i = 0' vs. 'int i(0)'(赋值与初始化计数变量)
- Linux vs Windows std::map 赋值构造函数(为什么会有这样的区别?)
- 编译-vs运行时常量变量赋值和C++中vlas的分配
- 构造函数初始化Vs赋值
- VS 2015更新3删除拷贝赋值操作符错误
- 成员初始化列表vs赋值/复制构造函数(在boost deadline_timer中)
- 显式赋值vs隐式赋值