C++ 从引用复制构造

C++ 从引用复制构造,c++,constructor,reference,copy-constructor,C++,Constructor,Reference,Copy Constructor,考虑一下这个代码 class Foo { private: Bar bar; //note: no reference public: Foo(Bar& b) : bar(b) { } }; Bar是否会构造副本?,这取决于显式或隐式定义的Bar的公共构造函数的签名 首先,C++标准允许引用的隐式转换,只要基础类型中唯一的差异是目标类型至少比源类型具有CV限定性,则使用本表中定义的部分排序(C++ 11,第3.3.3/4): 无简历合格者const 无cv限定符vola

考虑一下这个代码

class Foo {
private:
    Bar bar; //note: no reference

public:
   Foo(Bar& b) : bar(b) { }
};

Bar是否会构造副本?

,这取决于显式或隐式定义的
Bar的公共构造函数的签名

首先,C++标准允许引用的隐式转换,只要基础类型中唯一的差异是目标类型至少比源类型具有CV限定性,则使用本表中定义的部分排序(C++ 11,第3.3.3/4):

无简历合格者
const
无cv限定符volatile
无cv限定符const volatile
const
const volatile
volatile
const volatile

因此,考虑到这一点以及§12.8/2:

如果类
X
的非模板构造函数的第一个参数类型为
X&
const X&
volatile X&
const volatile X&
,并且没有其他参数,或者所有其他参数都有默认参数,则该类的非模板构造函数是副本构造函数

如果Bar具有具有以下任一签名的构造函数:

Bar(Bar&);
Bar(Bar const&);
Bar(Bar volatile&);
Bar(Bar const volatile&);
然后是,
b
将被复制构造到
Foo::bar


编辑:这是不正确的,我考虑的是
操作符=
和符合移动分配操作符资格的详细信息

请注意,可能有一个合格的构造函数不是复制构造函数:

Bar(Bar);

这将起作用(读:compile),但从技术上讲它不是一个复制构造函数。

是的,您的成员变量
bar
将被复制构造,这是使用初始值设定项列表而不是在构造函数体中赋值的好处之一

如果
Bar
类没有可访问的复制构造函数,并且编译器无法生成默认构造函数,则代码将无法编译


当您将引用传递给复制构造函数时,通常应将其设置为
常量
引用。

@ildjarn:还有什么其他可能性?(当然,除了无法编译之外。)@Oli:没有,我暂时感到困惑“这将起作用(读:编译)”。是吗?我手边没有标准的,但是@罗布:你说得对,我认为
运算符=
在按值获取其参数时,从技术上讲不是一个复制赋值运算符。我来编辑。谢谢。如果我有
Bar&Bar
Foo(Bar&b):Bar(b){}
。我是否错误地认为构造函数仍然会为
bar
调用,这意味着一个类型为
bar
的新对象?@Evgeni:是的,这是错误的。假定
bar
是该场景中的引用,则不执行任何复制,只执行别名。@Evgeni:注意,在类中保留引用会使该类不可赋值。在实践中,这通常是站不住脚的,最好使用类似
std::shared\u ptr
的方法来避免数据重复。