我有简单的程序:
#include <cmath>
int main()
{
for (int i = 0; i < 50; ++i)
std::sqrt(i);
}
Run Code Online (Sandbox Code Playgroud)
Clang 3.8优化了它-O3,但gcc 6.1没有.它产生以下组件:
## Annotations in comments added after the question was answered,
## for the benefit of future readers.
main:
pushq %rbx
xorl %ebx, %ebx
jmp .L2
.L4:
pxor %xmm0, %xmm0 # break cvtsi2sd's false dep on the old value of xmm0
pxor %xmm1, %xmm1 # xmm1 = 0.0
cvtsi2sd %ebx, %xmm0 # xmm0 = (double)i
ucomisd …Run Code Online (Sandbox Code Playgroud) 这个问题和我的回答让我想到了Python 2.7和Python 3.4之间的这种特殊区别.以简单的示例代码为例:
import timeit
import dis
c = 1000000
r = range(c)
def slow():
for pos in range(c):
r[pos:pos+3]
dis.dis(slow)
time = timeit.Timer(lambda: slow()).timeit(number=1)
print('%3.3f' % time)
Run Code Online (Sandbox Code Playgroud)
在Python 2.7中,我始终如一地获得0.165~Python 3.4 0.554~.反汇编之间唯一重要的区别是Python 2.7发出SLICE+3字节代码,而Python 3.4 BUILD_SLICE随后发出BINARY_SUBSCR.请注意,我已经从其他问题中消除了潜在减速的候选者,即字符串和xrangePython 3.4中不存在的事实(range无论如何,它应该与后者的类相似).
使用itertools' islice两者之间几乎完全相同的时间,所以我高度怀疑这是切片,这是造成差异的原因.
为什么会发生这种情况,是否存在指向行为变化的权威来源的链接?
编辑:为了回答答案,我已经将range对象包裹起来list,这确实给出了明显的加速.然而,当我增加迭代次数时,timeit我注意到时序差异变得越来越大.作为一个完整性检查,我替换切片与None看看会发生什么.
500次迭代timeit.
c = 1000000
r = list(range(c))
def slow():
for pos in …Run Code Online (Sandbox Code Playgroud) 在此示例代码中,有两个句子显示相同的静态变量.第一个没有歧义,但第二个没有,为什么?
#include <iostream>
using namespace std;
struct A { static const char a = 'a'; };
struct B : public A { };
struct C : public A { };
struct G : public B, public C { };
int main()
{
G v;
cout << G::B::A::a << endl;
cout << v.B::A::a << endl;
}
Run Code Online (Sandbox Code Playgroud)
GCC错误(根据一些评论,clang中没有歧义):
main.cpp:15:18: error: 'A' is an ambiguous base of 'G'
cout << v.B::A::a << endl;
Run Code Online (Sandbox Code Playgroud)
这段代码无效:
template <class T> struct A;
class C {
template <class T> friend void A<T>::foo();
};
Run Code Online (Sandbox Code Playgroud)
在GCC 6.1.0中它说:
error: member 'void A<T>::foo()' declared as friend before type 'A<T>' defined
template <class T> friend void A<T>::foo();
Run Code Online (Sandbox Code Playgroud)
Clang 3.8.0:
warning: dependent nested name specifier 'A<T>::' for friend class declaration
is not supported; turning off access control for 'C' [-Wunsupported-friend]
Run Code Online (Sandbox Code Playgroud)
Visual Studio 2015崩溃:
fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'f:\dd\vctools\compiler\cxxfe\sl\p1\c\template.cpp', line 8952)
template <class T> friend …Run Code Online (Sandbox Code Playgroud) 5.1.1/2表明:
关键字
this指定一个指向调用非静态成员函数(9.3.2)的对象的指针,或者计算非静态数据成员的初始值设定项(9.2).
和:
与其他上下文中的对象表达式不同
*this,为了成员函数体外的类成员访问(5.2.5),不需要它是完整类型.
以下代码打印8:
#include <cstddef>
#include <iostream>
struct Test
{
std::size_t sz = sizeof(this->sz);
};
int main()
{
std::cout << Test{}.sz;
}
Run Code Online (Sandbox Code Playgroud)
5.3.3说:
操作数是一个表达式,它是一个未评估的操作数(第5章),或带括号的type-id.的
sizeof操作者不得应用于具有功能或不完整的类型的表达式...
sizeof this->sz 有相同的结果.
this->在这种情况下被视为无操作,它基本上相当于sizeof(sz)?
让我们一起办理手续.
17.3.28有效但未指明的状态[defns.valid]
除了满足对象的不变量并且对象上的操作按其类型指定的操作之外,未指定的对象状态
[ 示例:如果
x类型的对象std::vector<int>处于有效但未指定的状态,x.empty()则可以无条件地调用,并且x.front()只有在x.empty()返回false时才能调用.- 结束例子 ]
一些用户认为这std::move(x).something()是荒谬的.但我无法理解之间的差异std::move(x).something()和y = std::move(x); y.something().注意:
// -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
std::vector<int> v;
v.pop_back();
// Error: attempt to access an element in an empty container.
Run Code Online (Sandbox Code Playgroud)
现在我们想尝试我们荒谬的案例:
std::vector<int> v(10);
std::move(v).pop_back();
Run Code Online (Sandbox Code Playgroud)
没错.这必须是每个人都在谈论的"有效但未指明",但让我们继续前进.
std::vector<int> v(10);
std::cout << std::move(v).size();
auto v2 = std::move(v);
std::cout << v.size();
Run Code Online (Sandbox Code Playgroud)
这打印100.这并不太令人惊讶.std::move它只是一个演员,它实际上并不执行移动构造函数的工作.
我错过了什么或者std::move(x).something()仍然是非感性的(除非是无操作)?
有关参考,请参阅有关成员函数.begin()和std :: begin()的注释以及upvoted答案.
以下示例表明v不会移动:
template< class …Run Code Online (Sandbox Code Playgroud) 我一直认为基类的公共方法确实被派生类继承,甚至认为派生类没有定义该特定方法.例如
#include <iostream>
using namespace std;
class A {
public:
int f() { cout << 3; return 0;}
int f(int x) {cout << x; return 0;}
};
class B: public A {
public:
int f() {std::cout << 5; return 0;}
};
int main(){
B ob;
ob.f(7);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期待结果是:7,但我得到编译错误说
" 错误:函数调用的参数太多,预期为0,有1;你的意思是'A :: f'吗? "
我知道错误试图说的是什么,但我很困惑,没有调用Base类的功能.
在C99中,§6.5.3.4:
2
sizeof运算符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的带括号的名称....4结果的值是实现定义的,其类型(无符号整数类型)
size_t在<stddef.h>(和其他头文件)中定义.
在C++ 14中,§5.3.3:
1
sizeof运算符产生其操作数的对象表示中的字节数....应用于任何其他基本类型(3.9.1)的sizeof的结果是实现定义的.
唯一保证的值是sizeof(char),sizeof(unsigned char)而且sizeof(signed char)是一个.
但是,"对象表示中的字节数"对我来说似乎很不错.例如,在C99§6.2.6.1中:
4存储在任何其他对象类型的非位字段对象中的值由n × CHAR_BIT位组成,其中n是该类型对象的大小(以字节为单位)....
那么为什么它是实现定义的,如果看起来很明确?
你们当中许多人似乎误解了我的问题.我从未声称:
A)类型的大小在所有系统上定义或相同,
B)实现定义意味着它可以返回"随机值"
我在这里得到的n * CHAR_BITS是一个固定的公式.公式本身不能在实现之间改变.是的,一个int可能是4个字节或8个字节.我明白了.但是在所有实现之间,值必须n * CHAR_BITS.
c++ ×7
c ×1
gcc ×1
optimization ×1
performance ×1
python ×1
python-2.7 ×1
python-3.4 ×1
sizeof ×1