C++引用可以赋值吗?
我一直在搞包装在容器类中的引用。为什么下面的代码合法,看起来行为正确?C++引用可以赋值吗?
#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)创建FooWrapper fw
与默认ctor后跟(2)分配从fw
到fw2
?我相信这不会发生,因为不能创建未初始化的引用,所以实际上将fw2
的创建视为复制构造?
我有时不清楚副本构建与分配的角色;他们似乎有时会流血,就像在这个例子中一样,但可能有一些我不知道的规则。我会很感激一个解释。
在下面的线,你正在构建fw2
通过使其成为fw
的副本。也就是说,您正在调用复制构造函数。
FooWrapper fw2 = fw;
例
下面是对如何default constructor,copy constructor,copy assignment operator,和move assignment operator(从C++ 11)被调用的(online)的例子。
#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
}
尽管=
的语法,FooWrapper fw2 = fw;
复制构造fw2
(使用复制构造函数)。根本不涉及默认构造和分配。
并回答标题中的问题:否,不能分配参考。如果你写的代码,试图实际上默认构造或分配FooWrapper
,如:
FooWrapper fw2;
fw2 = fw;
...这会失败。正式的,只需要一个“诊断”。非正式地说,我所知道的每个编译器都会拒绝编译它。
该初始化实际上调用了复制构造函数。 FooWrapper fw2 = fw;
,相当于 FooWrapper fw2(fw);
隐含定义拷贝构造函数并不需要创建一个未初始化的参考
参考: http://en.cppreference.com/w/cpp/language/copy_constructor
是的,这就是我的意思。改变了措辞'隐含定义拷贝constructor' –
措词还涉及到这样的事实,时下一个可以显式地请求编译器通过'default'关键字生成一个复制构造: 'CLASS_NAME(常量CLASS_NAME&)=默认值;' –