在堆栈上声明对象的两种方式之间的差异
Difference between two ways of declaring an object on the stack
假设我没有在Beatle
类中指定复制构造函数和operator=
,下面两个声明的区别是什么?
Beatle john(paul);
和
Beatle john = paul;
在对象赋值中,操作符=
隐式调用复制构造函数,除非另有说明。
它们是不同的语法结构。第一个是直接初始化,第二个是复制初始化。它们的行为几乎相同,只是后者需要非explicit
构造函数。*
都与赋值操作符无关,因为两行都是初始化。
换句话说:const int i = 4;
没问题,但const int i; i = 4;
不行。
*)更准确地说:如果相关构造函数声明为explicit
,则第二个版本不起作用。因此,更一般地说,直接初始化为您提供了一个"自由"转换:
struct Foo { Foo(std::string) {} };
Foo x("abc"); // OK: char(&)[4] -> const char * -> std::string -> Foo
Foo y = "abd"; // Error: no one-step implicit conversion of UDTs
要理解赋值操作符,只需将其分成几个部分。假设
Foo
有明显的operator=(const Foo & rhs)
。我们可以说x = y;
,它只是直接调用运算符,rhs
是y
。现在考虑这个:
x = "abc"; // error, no one-step implicit conversion
x = std::string("abc"); // fine, uses Foo(std::string), then copy
x = Foo("abc"); // fine, implicit char(&)[4] -> const char* -> std::string, then as above
第一个是直接初始化&第二个是拷贝初始化。
直接初始化意味着使用单个(可能是转换)构造函数初始化对象,相当于形式T t(u);
:
U u;
T t1(u); // calls T::T( U& ) or similar
复制初始化表示在必要时首先调用用户定义的转换之后,使用复制构造函数初始化对象,相当于形式T t = u;
:
T t2 = t1; // same type: calls T::T( T& ) or similar
T t3 = u; // different type: calls T::T( T(u) )
// or T::T( u.operator T() ) or similar
如果构造函数声明为explicit
,则复制初始化不起作用。
引用:
这个条目在Herb Sutter的GOTW中应该是一个很好的阅读。
回答您的编辑问题:=
在不同的用法中有不同的含义。
如果=
用于同时创建和初始化对象的表达式中,则=
不被视为赋值操作符,而被视为复制初始化操作符。
如果使用=
将一个对象赋值给另一个对象,在对象创建后,将导致调用赋值操作符。
相关文章:
- 在c代码之间共享数据的最佳方式
- C++:这两种将数字写入矩阵的方式之间是否存在显着的速度差异?
- 将函数作为参数传递的两种方式之间的区别
- 如何在Qt WebChannel中以独立于平台的方式在HTML/Javascript和C++之间进行通信?
- 如何以包装的方式初始化布局,从而减少布局之间的空间
- C++配置之间切换的最佳方式
- 这些在C 中初始化C数组的方式之间有区别吗?
- Qt中数据类(模型)和视图/控制器类之间的数据通信的正确方式是什么
- 消除有符号和无符号整数表达式之间比较的优雅方式
- 实时在语言之间流水线传输或以其他方式传输数据
- 找到组合对之间共享元素的最佳方式
- 使用内存集函数的各种方式之间的区别
- 这将是在将函数分配给变量或一次又一次地调用函数之间使用函数结果的最佳方式
- 成员类之间的通信的正确方式是什么?
- iOS和Android之间共享代码的最佳方式
- 逗号(,)在条件部分中两个表达式之间的for循环中的工作方式
- JScript 和 Windows 服务之间的通信方式
- 尝试在Qt中连接隐藏信号的两种方式之间做出决定
- 在堆栈上声明对象的两种方式之间的差异
- 在这两种包含相同标头的方式之间,编译器中是否发生了不同的事情