新手写出来的c++程序,估计到处都是可以优化的坑!
第一点
std::string str = "Hello";
std::vector<std::string> v;
cout<< "str.length is :" << str.length()<<endl;
cout<< "str.capacity is :"<< str.capacity()<<endl;
v.push_back(str); //使用push_back(const T&) 重载,调用时,会发生copy
std::cout << "After push_back 1, str is \"" << str << std::endl;
v.push_back(std::move(str));//会使用 push_back(T&&) 重载,不会发生copy,但是str 里面东西没了
std::cout << "After push_back 2, str is \"" << str << std::endl;
std::cout << "The contents of the vector are \"" << v[0]
<< ", " << v[1] << std::endl;
cout<< "str.length is :" << str.length()<<endl;
cout<< "str.capacity is :"<< str.capacity()<<endl;
输出如下:
str.length is :5
str.capacity is :15
After push_back 1, str is "Hello
After push_back 2, str is "
The contents of the vector are "Hello, Hello
str.length is :0
str.capacity is :15
第二点
定义了以下类和方法
class AAA{
private:
int aaa=5;
public:
~AAA()=default;
void show(){
cout << "AAA.aaa = "<< aaa<<endl;
}
};
void Test(std::unique_ptr<AAA> pp){
pp->show();
}
然后就很自然的写了以下调用
int main(int argc, char *argv[])
{
std::unique_ptr<AAA> pp = std::make_unique<AAA>();
Test(pp);// <--------注意这里
}
一编译就报错.
In function ‘int main(int, char**)’:
main.cpp:127:12: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = AAA; _Dp = std::default_delete<AAA>]’
127 | Test(pp);
| ^
很奇怪,
我调用一个参数为:std::unique_ptr<AAA>的函数,
按照要求,我传入了一个 std::unique_ptr<AAA> 类型的变量 pp,却无法编译通过.
改成这样就编译通过了:
int main(int argc, char *argv[])
{
std::unique_ptr<AAA> pp = std::make_unique<AAA>();
Test(std::move(pp)); // <-------------添加了std::move调用
}
输出为:
AAA.aaa = 5
然后继续,修改代码,看看move后发生了什么,
代码改为:
int main(int argc, char *argv[])
{
std::unique_ptr<AAA> pp = std::make_unique<AAA>();
Test(std::move(pp));
if(pp ==nullptr){
cout << "after call Test,pp is nullptr"<<endl;
}else
{
cout << "after call Test,pp is not nullptr"<<endl;
}
}
输出如下:
AAA.aaa = 5
after call Test,pp is nullptr
这就对了,move以后没了.
但还是有点区别:
- String 在move以后,本身没有变成null,但内容没有了.
- unique_ptr<>,在move以后,本身变成了null.
第三点
实际上是接着第二点的
我发现 std::unique_ptr<AAA> pp ,实际上是类unique_ptr<T>的一个实例,既然是类的实例,作为函数参数时,就应该使用引用方式. 以及右值引用方式,于是就改成了下面的代码(请手动忽略没加const的问题)
void Test(std::unique_ptr<AAA>& pp){
cout << "in Test(std::unique_ptr<AAA>& pp)" << endl;
pp->show();
}
void Test(std::unique_ptr<AAA>&& pp){
cout << "in Test(std::unique_ptr<AAA>&& pp)" << endl;
pp->show();
}
int main(int argc, char *argv[])
{
std::unique_ptr<AAA> pp = std::make_unique<AAA>();
Test(pp); //<--------------注意这里
if(pp ==nullptr){
cout << "after call Test,pp is nullptr"<<endl;
}else
{
cout << "after call Test,pp is not nullptr"<<endl;
}
}
输出为:
in Test(std::unique_ptr<AAA>& pp)
AAA.aaa = 5
after call Test,pp is not nullptr
看来调用的第一个引用参数的方法,由于没有使用std::move,调用后pp 不是nullptr.
然后再试:
std::unique_ptr<AAA> pp = std::make_unique<AAA>();
Test(std::move(pp));//<--------------注意这里
if(pp ==nullptr){
cout << "after call Test,pp is nullptr"<<endl;
}else
{
cout << "after call Test,pp is not nullptr"<<endl;
pp->show();
}
if(pp.get() == nullptr){
cout << "after call Test,pp.get() is nullptr"<<endl;
}else
{
cout << "after call Test,pp.get() is not nullptr"<<endl;
pp.get()->show();
}
这次使用了std::move,调用了右值引用参数的方法,但是结果有点意外:
in Test(std::unique_ptr<AAA>&& pp)
AAA.aaa = 5
after call Test,pp is not nullptr
AAA.aaa = 5
after call Test,pp.get() is not nullptr
AAA.aaa = 5
WTF,为啥 调用std::move之后竟然不变成nullptr.
不知对std::move的理解有问题还是实现有问题!!! 哭阿!