请考虑以下代码:
ifstream in;
try {
in.exceptions ( ifstream::failbit | ifstream::badbit );
in.open(pConfLocation);
} catch ( ifstream::failure e ) {
throw std::runtime_error("Can't open configuration file\n");
}
vector<string> lns;
string s;
in.clear();
while ( !in.eof() ){
getline( in, s );
boost::algorithm::trim(s);
lns.push_back( s+='\n');
}
Run Code Online (Sandbox Code Playgroud)
所以:
异常掩码是所有流对象的内部值,指定哪些状态标志在设置时必须抛出异常.
我没有设置ifstream :: eofbit,但无论如何在运行时出现以下错误:
terminate called after throwing an instance of 'std::ios_base::failure'
what(): basic_ios::clear
The program has unexpectedly finished.
Run Code Online (Sandbox Code Playgroud)
我无法理解这种行为.我试图在{}之前使用in.clear() …
我目前正在阅读Williams"C++ Concurrency in Action".现在我停止了专门用于实现无锁pop()的主题.
无锁弹出:
void pop(T& result)
{
node* old_head = head.load();
while(!head.compare_exchange_weak(old_head,old_head->next));
result=old_head->data;
}
Run Code Online (Sandbox Code Playgroud)
以下是对此代码的讨论的引用:
第二个问题是异常安全问题.当我们在第3章中首次介绍线程安全堆栈时,您看到如何按值返回对象会给您带来异常安全问题:如果在复制返回值时抛出异常,则该值将丢失.在这种情况下,传入对结果的引用是一个可接受的解决方案,因为如果抛出异常,您可以确保堆栈保持不变.不幸的是,在这里你没有那么奢侈; 一旦您知道自己是返回节点的唯一线程,您就只能安全地复制数据,这意味着该节点已从队列中删除.因此,通过引用传递返回值的目标不再是一个优点:您可能只是按值返回.如果要安全地返回值,则必须使用第3章中的其他选项:返回指向数据值的(智能)指针
我不明白引用的使用如何导致异常问题.我在这里看到'copy'这个词,但它不能用于引用,'初始化','赋值',但肯定不是'复制'.所以,我不明白在这个'副本'之后写的每一个.
谷歌搜索时,我找到了威廉姆斯的解释:https://forums.manning.com/posts/list/30887.page
但这并没有为我澄清这个问题,因为他再次使用带有参考文献的"复制":
"正常"堆栈:
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=data.top();
data.pop();
}
Run Code Online (Sandbox Code Playgroud)
使用"普通"堆栈,结果的参考参数的优点是您可以在从堆栈中删除节点之前复制结果,并且如果复制到结果抛出,则节点仍然在那里进行另一次调用采取.
这是我的问题:在这种情况下使用引用是否会导致异常的产生,以及为什么我可能只是按值返回?