1. 示例一
#include <iostream>
#include <string>
struct Obj{
Obj(){
std::cout << "Ctor called.\n";
}
Obj(const Obj&){
std::cout << "Copy ctor called.\n";
}
~Obj(){
std::cout << "Dtor called.\n";
}
};
void test1(const Obj& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template<typename T>
void test2(const T& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void test3(Obj& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template<typename T>
void test4(T& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void test5(Obj&& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
// 转发引用(万能引用)
template<typename T>
void test6(T&& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main () {
Obj obj;
const Obj obj2;
test1(obj);
test1(obj2);
test1(Obj{});
std::cout << std::string(30, '-') << std::endl;
test2(obj);
test2(obj2);
test2(Obj{});
std::cout << std::string(30, '-') << std::endl;
test3(obj);
//test3(obj2);
test4(obj);
test4(obj2); // T&接受const Obj
//test4(Obj{}); // T&不可能接受右值
std::cout << std::string(30, '-') << std::endl;
test5(Obj{});
std::cout << std::string(30, '-') << std::endl;
test6(obj);
test6(obj2);
test6(Obj{});
std::cout << std::string(30, '-') << std::endl;
}
输出结果:
Ctor called.
Ctor called.
void test1(const Obj&)
void test1(const Obj&)
Ctor called.
void test1(const Obj&)
Dtor called.
------------------------------
void test2(const T&) [with T = Obj]
void test2(const T&) [with T = Obj]
Ctor called.
void test2(const T&) [with T = Obj]
Dtor called.
------------------------------
void test3(Obj&)
void test4(T&) [with T = Obj]
void test4(T&) [with T = const Obj]
------------------------------
Ctor called.
void test5(Obj&&)
Dtor called.
------------------------------
void test6(T&&) [with T = Obj&]
void test6(T&&) [with T = const Obj&]
Ctor called.
void test6(T&&) [with T = Obj]
Dtor called.
------------------------------
Dtor called.
Dtor called.
2. 示例二
#include <iostream>
#include <string>
struct Obj{
Obj(){
std::cout << "Ctor called.\n";
}
Obj(const Obj&){
std::cout << "Copy ctor called.\n";
}
~Obj(){
std::cout << "Dtor called.\n";
}
};
void test(const Obj& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void test(Obj& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void test(Obj&& obj){
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template<typename T>
void verifyValueCategory(T&& obj){
if(std::is_lvalue_reference_v<T>){
std::cout << "T is a lvalue reference\n";
}
else if(std::is_rvalue_reference_v<T>){
std::cout << "T is a rvalue reference\n";
}
else {
std::cout << "T is not a reference\n";
}
test(std::forward<T>(obj));
}
template<typename T>
void verifyValueCategoryNoForward(T&& obj){
if(std::is_lvalue_reference_v<T>){
std::cout << "T is a lvalue reference\n";
}
else if(std::is_rvalue_reference_v<T>){
std::cout << "T is a rvalue reference\n";
}
else {
std::cout << "T is not a reference\n";
}
test(obj);
}
int main () {
Obj obj;
const Obj obj2;
std::cout << std::string(30, '-') << std::endl;
verifyValueCategory(obj); // void test(Obj&)
verifyValueCategory(obj2); // void test(const Obj&)
verifyValueCategory(Obj{}); // void test(Obj&&)
std::cout << std::string(30, '-') << std::endl;
verifyValueCategoryNoForward(obj);
verifyValueCategoryNoForward(obj2);
verifyValueCategoryNoForward(Obj{}); // 这里会有问题,会调用左值引用的版本而不是右值引用的版本
std::cout << std::string(30, '-') << std::endl;
Obj&& r = Obj{};
Obj&& r1 = Obj{};
test(r); // r是右值引用,但是r是变量因此属于左值,所以会调用void test(Obj&)的版本
test(std::move(r));
test(std::forward<decltype(r1)>(r1));
std::cout << std::string(30, '-') << std::endl;
}
输出结果:
Ctor called.
Ctor called.
------------------------------
T is a lvalue reference
void test(Obj&)
T is a lvalue reference
void test(const Obj&)
Ctor called.
T is not a reference
void test(Obj&&)
Dtor called.
------------------------------
T is a lvalue reference
void test(Obj&)
T is a lvalue reference
void test(const Obj&)
Ctor called.
T is not a reference
void test(Obj&)
Dtor called.
------------------------------
Ctor called.
Ctor called.
void test(Obj&)
void test(Obj&&)
void test(Obj&&)
------------------------------
Dtor called.
Dtor called.
Dtor called.
Dtor called.