新手寫出來的c++程序,估計到處都是可以優(yōu)化的坑!
第一點
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&) 重載,調(diào)用時,會發(fā)生copy
std::cout << "After push_back 1, str is \"" << str << std::endl;
v.push_back(std::move(str));//會使用 push_back(T&&) 重載,不會發(fā)生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();
}
然后就很自然的寫了以下調(diào)用
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);
| ^
很奇怪,
我調(diào)用一個參數(shù)為:std::unique_ptr<AAA>的函數(shù),
按照要求,我傳入了一個 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調(diào)用
}
輸出為:
AAA.aaa = 5
然后繼續(xù),修改代碼,看看move后發(fā)生了什么,
代碼改為:
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以后沒了.
但還是有點區(qū)別:
- String 在move以后,本身沒有變成null,但內(nèi)容沒有了.
- unique_ptr<>,在move以后,本身變成了null.
第三點
實際上是接著第二點的
我發(fā)現(xiàn) std::unique_ptr<AAA> pp ,實際上是類unique_ptr<T>的一個實例,既然是類的實例,作為函數(shù)參數(shù)時,就應(yīng)該使用引用方式. 以及右值引用方式,于是就改成了下面的代碼(請手動忽略沒加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
看來調(diào)用的第一個引用參數(shù)的方法,由于沒有使用std::move,調(diào)用后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,調(diào)用了右值引用參數(shù)的方法,但是結(jié)果有點意外:
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,為啥 調(diào)用std::move之后竟然不變成nullptr.
不知對std::move的理解有問題還是實現(xiàn)有問題!!! 哭阿!