一、C++标准库提供的是value语义
- 通常,所有容器都会建立元素拷贝,返回的也是元素的拷贝
- STL只支持value语义,不支持reference语义。优缺点如下:
- 优点:
- 复制元素很简单
- 使用reference时容易出错,你必须确保reference所指对象仍然健在,并需要小心队服偶尔出现的环式指向状态
- 缺点:
- 复制元素可能会导致不良的效率,有时甚至无法复制
- 无法在数个不同的容器中管理同一份对象
- 优点:
- 实现reference语义的两种做法:
- ①使用智能指针
- ②使用reference_wrapper
二、使用Shared Pointer
- C++标准库提供了许多智能指针。如果你打算在不同的容器之间共享对象,shared_ptr<>是一个适当的选择
演示案例
- 创建了一个Item类和一个printItems()函数用来打印类的内容
class Item { private: std:: string name; float price; public: Item( const std:: string& n, float p = 0) :name(n), price(p) {} std:: string getName()const { return name; } void setName(const std::string& n) { name = n; } float getPrice()const { return price; } void setPrice(float p) { price = p; } }; template< typename Coll> void printItems(const std::string& msg, const Coll& coll) { std:: cout << msg << std:: endl; for ( const auto& elem : coll) { std:: cout << " " << elem->getName() << ":" << elem->getPrice() << std:: endl; } }
- 测试程序如下:
int main() { typedef std:: shared_ptr<Item> ItemPtr; std:: set<ItemPtr> allItems; std:: deque<ItemPtr> bestsellers; //为bestsellers添加元素 bestsellers = { ItemPtr( new Item( "Kong Yize", 20.10)), ItemPtr( new Item( "A Midsummer Night's Dream", 14.99)), ItemPtr( new Item( "The Maltese Falcon", 9.88)) }; //为allItems添加元素 allItems = { ItemPtr( new Item( "Water", 0.44)), ItemPtr( new Item( "Pizza", 2.22)) }; //将bestsellers内的所有元素添加进allItems allItems.insert(bestsellers.begin(), bestsellers.end()); //打印一下bestsellers和allItems内的元素 printItems( "bestsellers", bestsellers); printItems( "allItems", allItems); std:: cout << std:: endl; //遍历bestsellers,将其内部的每一个对象的price加倍 for_each(bestsellers.begin(), bestsellers.end(), []( std:: shared_ptr<Item>& elem) {elem->setPrice(elem->getPrice() * 2);} ); //将bestsellers[1]的元素更改为allItems内名为“Pizza”的元素 bestsellers[ 1] = *( find_if(allItems.begin(), allItems.end(), []( std:: shared_ptr<Item> elem) { return elem->getName() == "Pizza"; }) ); //将bestsellers[0]对象的price设置为44.77 bestsellers[ 0]->setPrice( 44.77); //打印一下bestsellers和allItems内的元素 printItems( "bestsellers", bestsellers); printItems( "allItems", allItems); }
- 使用智能指针为set<>和deque<>创建元素,其内的每个元素都是智能指针。后面对set<>和deque<>进行了一系列的操作,由于智能指针是共享的,因此改变一者,另一者也改变
- 注意事项:使用shared_ptr<>会使事情变得复杂。例如,set<>容器内存储的是智能指针之后,不能再使用find()算法了,因此find()算法会找出拥有相等value的元素,现在比较的却是内部(由new返回)的pointer,因此只能使用find_if()算法
三、使用Reference Wrapper
- reference_wrapper在之前的文章介绍过,参阅:https://blog.csdn.net/qq_41453285/article/details/105454812
- reference_wrapper可以将传值调用改为传reference调用
- 假设保证“只要容器存在,被指向的元素一定存在”,那就可以使用reference_wrapper。见下面的演示案例
演示案例
- 此演示案例仍然使用到上面的Item类
int main() { std:: vector< std::reference_wrapper<Item>> books; Item f("Faust", 12.99); books.push_back(f); //将f的引入传递给books,现在books内存放的是f的引用 for ( const auto& book : books) { std:: cout << book.get().getName() << ": " << book.get().getPrice() << std:: endl; } //通过f改变内容 f.setPrice( 9.99); std:: cout << books[ 0].get().getPrice() << std:: endl; //可以看到vector内的也改变了 for ( const auto& book : books) { std:: cout << book.get().getName() << ": " << book.get().getPrice() << std:: endl; } }
- 这种做法的优点是不需要pointer语法。然而这个也有风险,因此此处使用reference而非显然意见
- 注意,下面的声明是不行的,因此其不是引用:
转载:https://blog.csdn.net/qq_41453285/article/details/105485576
查看评论