假设我们有程序void f(X2);。进一步假设我们有类型X1并且X2不共享继承层次结构。
我们想这样称呼它:f(X1{})并X1隐式转换为X2. 我们有两种选择来实现这一目标:
struct X2 {};
struct X1 { operator X2(); };
Run Code Online (Sandbox Code Playgroud)
struct X1 {};
struct X2 { X2(const X1&); };
Run Code Online (Sandbox Code Playgroud)
在实现方面,两者之间在定义顺序和访问私有数据的方式方面存在实际差异。
但从用户的角度来看,这两种方法是否会表现出不同的情况?如果是这样,两者中哪一个更可取?
即使我们对两者都进行标记,这个问题仍然是一样的explicit。然后出现的一个区别是,通过构造函数的转换仅在前一种情况下可用,但static_cast适用于任何一种情况。
c++ constructor conversion-operator implicit-conversion implicit-constructor
鉴于以下代码
#include <iostream>
using namespace std;
template <typename Type>
struct Something {
Something() {
cout << "Something()" << endl;
}
template <typename SomethingType>
Something(SomethingType&&) {
cout << "Something(SomethingType&&)" << endl;
}
};
int main() {
Something<int> something_else{Something<int>{}};
auto something = Something<int>{};
Something<int>{something};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到以下输出
Something()
Something()
Something(SomethingType&&)
Run Code Online (Sandbox Code Playgroud)
为什么复制构造函数被解析为模板化转发引用构造函数而不是移动构造函数?我猜这是因为移动构造函数是隐式定义的,而不是复制构造函数。但是在阅读了堆栈溢出中未隐式定义复制构造函数的情况后,我仍然感到困惑。
还有一次关于这一点,但相关的问题没有回答我的问题.
标准很清楚:
12.8复制和移动类对象,
§9
如果类X的定义没有显式声明移动构造函数,当且仅当
- X没有用户声明的复制构造函数时,将隐式声明为默认值,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的移动赋值运算符,
- X没有用户声明的析构函数,并且
- 移动构造函数不会被隐式定义为已删除.
[注意:当未隐式声明或显式提供移动构造函数时,否则将调用移动构造函数的表达式可能会调用复制构造函数. - 结束说明]
所以,在注意到最后的"Note"之前,我预计这段代码会无法编译(虽然我知道,移动应该回退到复制):
#include <iostream>
using std::cout;
class c
{
public:
c() { cout << "c::c()\n"; }
c( std::initializer_list< int > ) { cout << "c::c( std::initializer_list )\n"; };
c( const c& ) { cout << "c::c( const c& )\n"; }
c& operator=( const c& ) { cout << "c& c::operator=( const c& )\n"; return *this; }
~c() { cout << "c::~c()\n"; …Run Code Online (Sandbox Code Playgroud)