拷贝构造函数
class A{
A(const A& a);
};
问题:
- 参数是否一定要加const?
1. 拷贝构造函数的参数
- 1.1 使用不加const的拷贝构造函数
#include <iostream>
class A {
public:
A(){std::cout << "A construct." << std::endl;}
~A(){std::cout << "A desconstruct." << std::endl;}
A(A& a){std::cout << "A copy construct" << std::endl;}
//A(const A& a){std::cout << "A const copy construct" << std::endl;}
};
int main(int argc, char** argv) {
A a1;
A a2 = a1;
}
- 运行:
A construct.
A copy construct
A desconstruct.
A desconstruct.
- 1.2 使用加const的拷贝构造函数
#include <iostream>
class A {
public:
A(){std::cout << "A construct." << std::endl;}
~A(){std::cout << "A desconstruct." << std::endl;}
//A(A& a){std::cout << "A copy construct" << std::endl;}
A(const A& a){std::cout << "A const copy construct" << std::endl;}
};
int main(int argc, char** argv) {
A a1;
A a2 = a1;
}
- 运行:
A construct.
A const copy construct
A desconstruct.
A desconstruct.
- 1.3 同时存在加const和不加const的拷贝构造函数
#include <iostream>
class A {
public:
A(){std::cout << "A construct." << std::endl;}
~A(){std::cout << "A desconstruct." << std::endl;}
A(A& a){std::cout << "A copy construct" << std::endl;}
A(const A& a){std::cout << "A const copy construct" << std::endl;}
};
int main(int argc, char** argv) {
A a1;
A a2 = a1;
const A a3;
A a4 = a3;
}
- 运行:
A construct.
A copy construct
A construct.
A const copy construct
A desconstruct.
A desconstruct.
A desconstruct.
A desconstruct.
- 1.4 只存在不加const的拷贝构造函数,异常情况1:
#include <iostream>
class A {
public:
A(){std::cout << "A construct." << std::endl;}
~A(){std::cout << "A desconstruct." << std::endl;}
A(A& a){std::cout << "A copy construct" << std::endl;}
//A(const A& a){std::cout << "A const copy construct" << std::endl;}
};
int main(int argc, char** argv) {
A a1;
A a2 = a1;
const A a3;
A a4 = a3;
}
- 编译错误: 因为a3是常量
copy_construct.cpp: In function ‘int main(int, char**)’:
copy_construct.cpp:18:9: error: binding ‘const A’ to reference of type ‘A&’ discards qualifiers
A a4 = a3;
^
copy_construct.cpp:7:2: note: initializing argument 1 of ‘A::A(A&)’
A(A& a){std::cout << "A copy construct" << std::endl;}
-
1.5 只存在不加const的拷贝构造函数,异常情况2:
#include <iostream> class A { public: A(){std::cout << "A construct." << std::endl;} ~A(){std::cout << "A desconstruct." << std::endl;} A(A& a){std::cout << "A copy construct" << std::endl;} //A(const A& a){std::cout << "A const copy construct" << std::endl;} }; A fun() { return A(); } int main(int argc, char** argv) { A a1; A a2 = a1; A a3 = fun(); }
编译失败: 编译器生成的临时返回对象是常引用类型, 因为随后临时对象赋值给其它变量时,不需要被赋值的变量去修改它;
copy_construct.cpp: In function ‘A fun()’: copy_construct.cpp:14:11: error: invalid initialization of non-const reference of type ‘A&’ from an rvalue of type ‘A’ return A(); ^ copy_construct.cpp:7:2: note: initializing argument 1 of ‘A::A(A&)’ A(A& a){std::cout << "A copy construct" << std::endl;} ^ copy_construct.cpp: In function ‘int main(int, char**)’: copy_construct.cpp:21:12: error: invalid initialization of non-const reference of type ‘A&’ from an rvalue of type ‘A’ A a3 = fun(); ^ copy_construct.cpp:7:2: note: initializing argument 1 of ‘A::A(A&)’ A(A& a){std::cout << "A copy construct" << std::endl;}
-
1.6 总结:
**1. 拷贝构造函数的参数可以是A&, 也可以是const A&; **
2.如果同时存在两个拷贝构造函数, 参数分别为A&和const A&, 那么系统会根据实参类型选择拷贝构造函数
3. 如果只使用非const参数的拷贝构造函数,那么程序在编译拷贝构造函数时需要常量, 就会导致编译失败.
**4. 通常我们只编写一个带有const类型的拷贝构造函数, 就可以适应所有情况了. **