我一直在搞乱容器类中包含的引用。为什么以下代码合法且看起来行为正确?
#include <iostream>
class Foo
{
public:
Foo( int i ) : i_( i ) {}
int i_;
};
class FooWrapper
{
public:
FooWrapper( Foo& foo ) : foo_( foo ) {}
Foo& foo_;
};
int main( int argc, char* argv[] )
{
Foo foo( 42 );
FooWrapper fw( foo );
FooWrapper fw2 = fw;
std::cout << fw2.foo_.i_ << std::endl;
return 0;
}
如果没有明确的operator=
,我相信C ++会做成员副本。所以当我FooWrapper fw2 = fw;
时,这不是两个操作:(1)使用默认的ctor创建FooWrapper fw
,然后是(2)从fw
到fw2
的分配?我确信这不会发生,因为无法创建未初始化的引用,所以fw2
的创建实际上被视为复制构造吗?
我有时不清楚复制构造与作业的作用;它们似乎有时会相互渗透,就像在这个例子中一样,但可能有一些我不知道的规则。我很感激解释。
答案 0 :(得分:4)
尽管语法中有FooWrapper fw2 = fw;
,fw2
复制构造FooWrapper
(使用复制构造函数)。根本不涉及默认构造或分配。
要回答标题中的问题:不,不能分配引用。如果您编写了试图实际默认构造或分配FooWrapper fw2;
fw2 = fw;
的代码,例如:
{{1}}
......这会失败。官方说来,只有一个&#34;诊断&#34;是必须的。非正式地,我所知道的每个编译器都会拒绝编译它。
答案 1 :(得分:3)
这个初始化实际上调用了复制构造函数。
FooWrapper fw2 = fw;
并相当于
FooWrapper fw2(fw);
隐式定义的复制构造函数不需要创建未初始化的引用
供参考: http://en.cppreference.com/w/cpp/language/copy_constructor
答案 2 :(得分:3)
在下面的一行中,您将fw2
复制为fw
。也就是说,您正在调用复制构造函数。
FooWrapper fw2 = fw;
示例强>
以下是online,default constructor,copy constructor和copy assignment operator(来自C ++ 11)的调用示例(move assignment operator)。
#include <iostream>
struct foo
{
foo() {std::cout << "Default constructor" << '\n';}
foo(foo const&) {std::cout << "Copy constructor" << '\n';}
foo& operator=(foo const&) {std::cout << "Copy assignment operator" << '\n'; return *this; }
foo& operator=(foo &&) {std::cout << "Move assignment operator" << '\n'; return *this; }
};
int main( int argc, char* argv[] )
{
foo a; // Default constructor
foo b = a; // Copy constructor
foo c; // Default constructor
c = b; // Copy assignment operator
b = std::move(c); // Move assignment operator
}