在这里阅读关于转换运算符和构造函数的一些问题让我思考它们之间的相互作用,即当存在"模糊"调用时.请考虑以下代码:
class A;
class B {
public:
B(){}
B(const A&) //conversion constructor
{
cout << "called B's conversion constructor" << endl;
}
};
class A {
public:
operator B() //conversion operator
{
cout << "called A's conversion operator" << endl;
return B();
}
};
int main()
{
B b = A(); //what should be called here? apparently, A::operator B()
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码显示"被称为A的转换运算符",这意味着调用转换运算符而不是构造函数.如果operator B()从中删除/注释掉代码A,编译器将很乐意切换到使用构造函数(不对代码进行其他更改).
我的问题是:
B b = A();是一个模糊的调用,因此这里必须有某种类型的优先级.这个优先权究竟在哪里确定?(将赞赏C++标准的参考/引用)A对象应该如何成为一个B对象, …c++ constructor operators type-conversion conversion-operator
初始化,直接和复制初始化有两种语法:
A a(b);
A a = b;
Run Code Online (Sandbox Code Playgroud)
我想知道他们有不同定义行为的动机.对于复制初始化,涉及额外的副本,我不能想到该副本的任何目的.由于它是来自临时文件的副本,它可以并且可能会被优化,因此用户不能依赖它发生 - 因为额外的副本本身不足以应对不同的行为.所以为什么?
可能重复:
复制初始化和直接初始化之间的C++是否存在差异?
我刚开始学习C++.
为了用值初始化变量,我遇到了
int a = 0;
Run Code Online (Sandbox Code Playgroud)
和
int a(0);
Run Code Online (Sandbox Code Playgroud)
这让我很困惑.我可以知道哪种方法最好吗?
可能重复:
复制初始化和赋值初始化之间的C++是否存在差异?
有什么区别
T a(b);
Run Code Online (Sandbox Code Playgroud)
和
T a = b;
Run Code Online (Sandbox Code Playgroud)
和
T a = T(b);
Run Code Online (Sandbox Code Playgroud)
?
我从一开始就学习C++而且我没有得到整个字符串主题.
以下三个代码有什么区别?
std::string s = std::string("foo"); std::string s = new std::string("foo"); std::string s = "foo";这段代码:
class X {
int member;
};
volatile X a;
X b = a;
Run Code Online (Sandbox Code Playgroud)
失败并出现错误:
prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’
prog.cpp:6:7: note: candidates are:
prog.cpp:1:7: note: X::X()
prog.cpp:1:7: note: candidate expects 0 arguments, 1 provided
prog.cpp:1:7: note: X::X(const X&)
prog.cpp:1:7: note: no known conversion for argument 1 from ‘volatile X’ to ‘const X&’
Run Code Online (Sandbox Code Playgroud)
有什么办法可以让编译器为我生成易失性复制构造函数吗?
两者之间有什么区别吗?
std::string s1("foo");
Run Code Online (Sandbox Code Playgroud)
和
std::string s2 = "foo";
Run Code Online (Sandbox Code Playgroud)
?
Nicolai M. Josuttis的C++标准库声明:
两者之间存在细微差别
X x;
Y y(x) //explicit conversion
Run Code Online (Sandbox Code Playgroud)
和
X x;
Y y = x; //implicit conversion
Run Code Online (Sandbox Code Playgroud)
接下来说:"前者通过使用类型X的显式转换创建Y类型的新对象,而后者通过使用隐式转换创建类型为Y的新对象."
我猜对于显式与隐式转换的概念我有点困惑.在这两种情况下,你都使用X并将其推入Y本身 - 一个使用Y的构造函数,一个使用赋值运算符.
在这两种情况下如何处理转换有什么不同,是什么使它显式/隐式,以及如何使用"显式"关键字定义类构造函数(如果有的话)?
struct X {
X (int x) {}
};
int main() {
X x1(0); // nothing!
X x2 = 0; // warning: unused variable
X x3 = X(0); // warning: unused variable
}
Run Code Online (Sandbox Code Playgroud)
为什么没有生成警告x1?
我正在编译-Wall选项.
GCC和Clang都产生相同的输出.
这3行生成相同的汇编指令(asm("nop")为清楚起见放置一些):
nop
lea -0x8(%rbp),%rdi
mov $0x0,%esi
callq 400600 <X::X(int)>
nop
lea -0x10(%rbp),%rdi
mov $0x0,%esi
callq 400600 <X::X(int)>
nop
lea -0x18(%rbp),%rdi
mov $0x0,%esi
callq 400600 <X::X(int)>
nop
Run Code Online (Sandbox Code Playgroud)原始类型(例如,typedef int X)不会发生这种情况.
如果原因涉及构造函数中可能存在副作用的事实,则问题变为:为什么我会得到另外两个警告?
考虑以下代码:
struct X{
explicit X(){}
explicit X(const X&){}
};
void foo(X a = X()){}
int main(){}
Run Code Online (Sandbox Code Playgroud)
使用C++ 14标准,GCC 7.1和clang 4.0都拒绝代码,这正是我所期望的.
但是,使用C++ 17(-std=c++1z),它们都接受代码.什么规则变了?
对于两个编译器都表现出同样的行为,我怀疑这是一个bug.但据我所知,最新的草案仍然说,默认参数使用复制初始化 1的语义.同样,我们知道explicit构造函数只允许直接初始化 2.