参考链接:
https://www.cnblogs.com/virusolf/p/4903717.html
http://dongxicheng.org/cpp/effective-stl-part1/
int f(double(d));
int f(double d);
int f(double);
下列语句都声明了一个返回值为int类型的函数g,它的参数是返回值为double类型且无参的函数指针。
int g(double(*pf)());
int g(double pf());
int g(double ()); //注意与int g(double (f))的区别
对于如下语句,编译器会做出这样的解释:声明了一个返回值为listifstream dataFile("ints.dat");
list data(istream_iterator(dataFile),istream_iterator());
如果希望构造一个listifstream dataFile("ints.dat");
istream_iterator dataBegin(dataFile);
istream_iterator dataEnd;
list data(dataBegin,dataEnd);
class widget
{
...
};
doSth()
{
widget w; //一次构造函数
vector v;
v.push_back(w); //一次拷贝构造函数
} // 两次析构函数
但如果容器中包含的是指针的话,一旦没有特别将指针delete掉将会发生内存泄漏。
class widget
{
...
};
doSth()
{
widget* w = new widget();
vector v;
v.push_back(w);
} // memory leak!!!
最为方便并且能够保证异常安全的做法是将容器所保存的对象定义为 带有引用计数的智能指针。
class widget
{
...
};
doSth()
{
shared_ptr w(new widget()); //构造函数一次
vector> v;
v.push_back(w);
} //析构函数一次 没有内存泄漏
auto_ptr p1(new int(1)); // p1 = 1
auto_ptr p2(new int(2)); // p2 = 2
p2 = p1; // p2 = 1 p1 = emtpy;
第三条提到STL容器中的插入对象和读取对象,使用的都是对象的拷贝,并且基于STL容器的算法也通常需要进行对象的copy,所以,创建包含auto_ptr的容器是不明智的。
Container c;
而你想把c中所有值为1963的对象都去,则不同的容器类型采用的方法不同,没有一种是通用的。
c.erase(remove(c.begin(), c.end(), 1963), // 当c是vector、string
c.end()); // 或deque时,erase-remove惯用法是去除特定值的元素的最佳方法
[2] 对于list,最有效的方法是直接使用remove函数:
c.remove(1963);
[3] 对于关联容器,解决问题的适当方法是调用erase:
c.erase(1963); // 当c是标准关联容器时,erase成员函数是去除特定值的元素的最佳方法
(2)让我们换一下问题:不是从c中除去每个有特定值的元素,而是消除下面判断式返回真的每个对象:
bool badValue(int x); // 返回x是否是“bad”
[1] 对于序列容器(vector、list、deque和string),只需要将remove换成remove_if即可:
c.erase(remove_if(c.begin(), c.end(), badValue), // 当c是vector、string
c.end()); // 或deque时这是去掉badValue返回真的对象的最佳方法
c.remove_if(badValue); // 当c是list时这是去掉badValue返回真的对象的最佳方法
[2] 对于关联容器,有两种方法处理该问题,一个更容易编码,另一个更高效。“更容
AssocContainer c; // c现在是一种标准关联容器
AssocContainer goodValues; // 用于容纳不删除的值的临时容器
remove_copy_if(c.begin(), c.end(), // 从c拷贝不删除
inserter(goodValues, // 的值到
goodValues.end()), // goodValues
badValue);
c.swap(goodValues); // 交换c和goodValues的内容
“更高效”的解决方案是直接从原容器删除元素。不过,因为关联容器没有提供类似remove_if的成员函数,所以我们必须写一个循环来迭代c中的元素,和原来一样删除元素:
AssocContainer c;
...
for (AssocContainer::iterator i = c.begin(); // for循环的第三部分
i != c.end(); // 是空的;i现在在下面
/*nothing*/ ){ // 自增
if (badValue(*i)) c.erase(i++); // 对于坏的值,把当前的
else ++i; // i传给erase,然后
} // 作为副作用增加i;对于好的值,只增加i
(3)进一步丰富该问题:不仅删除badValue返回真的每个元素,而且每当一个元素被删掉时,我们也想把一条消息写到日志文件中。
ofstream logFile; // 要写入的日志文件
AssocContainer c;
...
for (AssocContainer::iterator i = c.begin(); // 循环条件和前面一样
i !=c.end();){
if (badValue(*i)){
logFile << "Erasing " << *i <<'\n'; // 写日志文件
c.erase(i++); // 删除元素
}
else ++i;
}
[2] 对于vector、string、list和deque,必须利用erase的返回值。那个返回值正是我们需要的:一旦删除完成,它就是指向紧接在被删元素之后的元素的有效迭代器。换句话说,我们这么写:
for (SeqContainer::iterator i = c.begin();
i != c.end();){
if (badValue(*i)){
logFile << "Erasing " << *i << '\n';
i = c.erase(i); // 通过把erase的返回值赋给i来保持i有效
}
else
++i;
}
template
class lock
{
public:
Lock(const Container& container):c(container)
{
getMutexFor(c);
}
~Lock()
{
releaseMutex(c);
}
private:
Container& c;
},
vector v;
...
{
Lock> lock(v); //构造lock,加锁v
doSthSync(v); //对v进行多线程的操作
} //析构lock,解锁v