拷貝建構式的第一個引數要求是自身型別的參考,但是沒有一定要求具有底層const屬性即對常量的參考,但是使用時最好加上const,原因是我們可能在某些“不知道”的情況下對常量物件呼叫拷貝建構式,
來看一個例子
class HasPtr{
public:
HasPtr(const std::string &s=std::string()):ps(new std::string(s)),i(0){
std::cout<<"construction call"<<std::endl;
}
HasPtr(HasPtr &hasptr):i(hasptr.i),ps(new std::string(*hasptr.ps))
{
std::cout<<"copy construction call"<<std::endl;;
}
~HasPtr()
{ delete ps;
std::cout<<"deconstruction call"<<std::endl; }
private:
std::string *ps;
int i;
};
int main()
{
HasPtr ptr1("a"),ptr2("c"),ptr3("b");
std::vector<HasPtr> vec{ptr1,ptr2,ptr3};
return 0;
}
上面的例子中定義了一個類HasPtr,此類包含一個引數為自身型別參考的拷貝建構式,主程式中構造了三個類的實體化物件,使用初始化串列的方式將其放入容器vector中,看上去好像沒有什么問題,但是這個例子會在編譯期出錯,
error: cannot bind non-const lvalue reference of type ‘HasPtr&’ to an rvalue of type ‘HasPtr’
程式中所有地方均使用HasPtr的物件均為左值為什么會報無法從非常量的左值無法系結到右值上去?
答案是,在初始化初始化串列的時候,vector的建構式匹配vector<T>(initializer_list<T>)這個建構式,而initializer_list<T>的元素均為const,這里程式作了三個操作:
1、首先將初始化串列中的值拷貝構造到initializer_list中,此處HasPtr具有了const屬性,成為了一個右值,(產生三個物件)
2、然后程式將initializer_list中的元素拷貝構造到vector中 (產生三個物件)
3、銷毀initializer_list中的元素 (銷毀三個物件)
上述第二步操作需要呼叫引數為const HasPtr &的拷貝建構式,而我們提供的是非const版本的,所以需要隱式轉換,但顯然這樣的轉換是失敗的,所以產生上述錯誤,
總結:1、拷貝建構式的第一個引數最好帶上const
2、包含初始化串列的容器操作可能會呼叫兩次拷貝建構式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/280601.html
標籤:C++
上一篇:JUC包的執行緒池詳解
