在Bjarne Stroustrup的"C++编程语言"第4版36.3.6
STL类操作部分中,以下代码用作链接示例:
void f2()
{
std::string s = "but I have heard it works even if you don't believe in it" ;
s.replace(0, 4, "" ).replace( s.find( "even" ), 4, "only" )
.replace( s.find( " don't" ), 6, "" );
assert( s == "I have heard it works only if you believe in it" ) ;
}
Run Code Online (Sandbox Code Playgroud)
断言失败gcc
(看到它直播)和Visual Studio
(看到它的实时),但它在使用Clang时没有失败(请参见实时).
为什么我会得到不同的结果?这些编译器是否错误地评估了链接表达式,或者此代码是否表现出某种形式的未指定 …
c++ operator-precedence language-lawyer unspecified-behavior c++11
在典型的C++代码中,C++ 17评估顺序保证(P0145)投票的含义是什么?
对于像这样的事情,它有什么变化
i=1;
f(i++, i)
Run Code Online (Sandbox Code Playgroud)
和
std::cout << f() << f() << f() ;
Run Code Online (Sandbox Code Playgroud)
要么
f(g(),h(),j());
Run Code Online (Sandbox Code Playgroud) 我有一些(C++ 14)代码,如下所示:
map<int, set<string>> junk;
for (int id : GenerateIds()) {
try {
set<string> stuff = GetStuff();
junk[id] = stuff;
} catch (const StuffException& e) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
这有效.有时GetStuff()
抛出一个异常,这很好,因为如果它,我不想在垃圾地图中的值.
但起初我在循环中写了这个,这不起作用:
junk[id] = GetStuff();
Run Code Online (Sandbox Code Playgroud)
更确切地说,即使GetStuff()
抛出异常,junk[id]
也会创建(并分配一个空集).
这不是我所期望的:我希望它们以相同的方式运行.
我在这里误解了C++的原理吗?
考虑以下代码:
std::unordered_map<int, std::string> data;
data[5] = foo();
Run Code Online (Sandbox Code Playgroud)
按照什么顺序data[5]
和foo()
处理?如果foo()
抛出异常,是否创建了5
项目data
?
如果行为取决于C++的版本,那些版本有何不同?
当访问 unique_ptr->get_id() 时,这会导致分段错误,因为 release() 是预先运行的。
这里不保证顺序吗?
#include <iostream>
#include <memory>
#include <unordered_map>
class D
{
private:
int id_;
public:
D(int id) : id_{id} { std::cout << "D::D\n"; }
~D() { std::cout << "D::~D\n"; }
int get_id() { return id_; }
void bar() { std::cout << "D::bar\n"; }
};
int main() {
std::unordered_map<int, D*> obj_map;
auto uniq_ptr = std::make_unique<D>(123);
obj_map[uniq_ptr->get_id()] = uniq_ptr.release();
obj_map.at(123)->bar();
return 0;
}
Run Code Online (Sandbox Code Playgroud) 以下代码在clang ++中有效,但在g ++中崩溃了
#include<vector>
#include<iostream>
template<class Iterator>
double abs_sum(double current_sum, Iterator it, Iterator it_end){
if (it == it_end)
return current_sum;
return abs_sum(current_sum+std::abs(*it),++it,it_end);
}
int main(int argc, char** argv){
std::vector<double> values {1.0, 2.0,-5};
std::cout << abs_sum(0.0,values.begin(),values.end()) << std::endl;;
}
Run Code Online (Sandbox Code Playgroud)
罪魁祸首证明是这条线:
return abs_sum(current_sum+std::abs(*it),++it,it_end);
Run Code Online (Sandbox Code Playgroud)
在clang中,*it
在之前进行评估++it
,在g ++中它是相反的,导致迭代器在被解除引用之前被增加.事实证明,评估函数参数的顺序是实现定义的.
我的问题是:我如何捕获此类错误?理想情况下,当我意外地依赖于具体实施细节时,我想要出错或至少发出警告.
即使用-Wall,clang和gcc都不会发出任何警告.
I've read from Order of evaluation, and I don't understand it well. Does the order mean the execution order in run time or just the logic order in the source code?
Let's see a code snippet as below:
void f()
{
int a = 10; // A
int b = 20; // B
//...
}
Run Code Online (Sandbox Code Playgroud)
Does it mean that expression A
is sequenced before expression B
?
And is the c++ compiler allowed to reorder the code as below? …