我在下面的代码中有一些关于ebp,esp和stack frame的问题.
为什么我们从esp中减去28?我们在main中有两个局部变量x和y.那么为什么我们不减8?
我们不是把值从右到左叠加?那么为什么我们在[eax + 8]而不是[eax + 4]中添加1?
我对这个结构有点困惑.你能帮我吗?谢谢.
func(int a, int b, int c)
{
return a+b+c;
}
main()
{
int x, y=3;
x=func(y,2,1);
}
Run Code Online (Sandbox Code Playgroud)
考虑一个例子。
#include <string>
struct S {
S() {
new (&s) std::string("hi");
}
~S() {
// does not compile
// s.~std::string();
// compiles
using std::string;
s.~string();
}
union {
std::string s;
};
};
Run Code Online (Sandbox Code Playgroud)
为什么注释掉的部分不能编译?
我从 clang 得到的错误消息表明编译器将std自身解析为一种类型。
对象销毁表达式中的标识符“std”未命名类型
为什么编译器不能确定这std::string是类型?这在某种程度上是模棱两可的吗?
我从 Andrei Alexandrescu 的演讲中了解到这一点。现在是 37:10。他很快评论说,如果类型名称是合格的,这“不会解析”,但没有解释原因。
(我使用“解析”这个词主要是因为他这样做了,我没有想到更好的词。不要读得太深。我并不是说编译器做错了什么。)
使用 CMake,是否有一种方法可以生成构建系统,如果共享库的源代码更改而不更改其标头,则不会重新链接下游的所有内容?
在 Makefiles 中,我在共享库本身上使用了一个只有订单先决条件的规则,并在库头上使用了常规先决条件来获得这种效果。
我知道这并不能严格保证生成正确的构建,例如您可以从共享库中删除函数定义,但这是为了快速重建调试构建,根据我的经验,它几乎总是产生正确的构建。我想有一两次我遇到了运行时链接器错误,但在那种奇怪的情况下,像往常一样运行构建并没有太大的麻烦。
尽管如此,如果有充分的理由表明这实际上是一个糟糕的想法并且不应该这样做,那也可能是一个答案。
这是来自英特尔Embree代码中的 vec3fa.h .
struct __aligned(16) Vec3fa
{
typedef float Scalar;
enum { N = 3 };
union {
__m128 m128;
struct { float x,y,z; union { int a; float w; }; };
};
// other stuff in struct
};
Run Code Online (Sandbox Code Playgroud)
外联盟在做什么?内心联盟对我来说更加神秘.代码中从不引用a和w变量.
看起来这为使用适当的别名读取和写入m128,x,y和z提供了一种方便而干净的方式.它是如何工作的?
int如何参与?
在讨论并发性和C++ 11内存模型时,Herb Sutter给出了非法优化的例子.
http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2
从第17分钟的幻灯片:
void f(vector<widget>& v) {
if(v.length()>0) xMutex.lock();
for(int i = 0; i < v.length(); ++i)
++x; // write is conditional
if(v.length()>0) xMutex.unlock();
}
Run Code Online (Sandbox Code Playgroud)
"很可能(如果存在严重缺陷)中央循环的转变:"
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1; // oops: write is not conditional
x = r1;
Run Code Online (Sandbox Code Playgroud)
他解释说,"......这个写入不是有条件的,即使doOptionalWork为false,它也会在每次执行时发生,这将注入一个不受互斥锁保护的写入,这会引发竞争..."
为什么他说发明的写不受互斥锁的保护?我理解完整的转换如下所述.
// "optimized" version 1
void f(vector<widget>& v) {
if(v.length() > 0) xMutex.lock()
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1;
x = r1;
if(v.length() > …Run Code Online (Sandbox Code Playgroud) 与继承虚拟功能不同,解析虚拟继承似乎是枯燥无味的,但也许我只是没有创造力(狡猾?).
虚拟继承是否与虚函数的继承有关?具体来说,虚拟继承是否会引发后期绑定?我看不出任何理由.由于关键字过载,我只是怀疑.
我意识到标准没有指定虚拟继承的实现.我对大多数非假想的机器都感兴趣,但不完美.
c++ virtual-functions multiple-inheritance virtual-inheritance
这个链接的问题询问make_shared<>函数和shared_ptr<>构造函数是否不同.
部分答案是,make_shared<>通常会在单个分配中为指向对象和智能指针控制块分配内存.该shared_ptr<>构造函数使用两个分配.
cppreference指出构造函数"必须"这样做,但没有给出任何理由.
为什么是这样?是出于某种原因不可能吗?或者由于其他原因,标准是否禁止它?
在24.2.3 Input iterators,C++标准指定输入迭代器的一个要求作为表达式(void)r++等效(void)++r.
你也可以在cppreference上看到这个.
那是什么表达?这个要求有什么意义?为什么需要?
它看起来像一个C风格的类型转换为void的结果r++还是++r,但我不认为这是它到底是什么.这就是说,稍微离题,看起来我可以void在类中定义转换运算符.gcc和clang都编译它,但clang发出警告:
警告:永远不会使用将'C'转换为'void'的转换函数
std::allocator_traits 当我提供一个具有单个模板参数的分配器的STL样式容器时,它会自动运行它的魔法,但是当我提供一个STL样式的容器时,它没有一个具有两个模板参数但其他类似的分配器.
std::allocator_traits如何与具有多个模板参数的分配器进行交互,我需要做什么?std::allocator_traits在这种情况下是否可以提供合理的默认值?
作为一个例子,如果我采用简单的分配器Howard Hinnant在Allocator Boilerplate中提供并将其提供给std::vector<>那么一切都很好.如果我int向allocator模板添加一个虚拟参数(并根据需要进行轻微修改),那么我会遇到编译器错误,因为编译器无法找到rebind其他内容.
这是代码中的描述:
http://coliru.stacked-crooked.com/a/173c57264137a351
如果我必须std::allocator_traits在这种情况下专注自己,有没有办法仍然获得默认值?
请考虑以下代码:
#include <stdio.h>
int main()
{
static int counter=5;
printf ("Counter = %d\n", counter);
if (counter--)
{
main();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译:
gcc test.c -ansi -Wall –pedantic
Run Code Online (Sandbox Code Playgroud)
执行:
[root@mars home]# ./a.out
Counter = 5
Counter = 4
Counter = 3
Counter = 2
Counter = 1
Counter = 0
Run Code Online (Sandbox Code Playgroud)
这里main()调用自己().
似乎main()每次main()调用函数的原始堆栈帧时都会被覆盖.
但回信地址是什么?函数可以返回自己的堆栈框架吗?
请帮我澄清这个疑问.
谢谢.
c++ ×8
c++11 ×3
stack-frame ×2
allocator ×1
assembly ×1
c ×1
c++14 ×1
cmake ×1
concurrency ×1
destructor ×1
intel ×1
intrinsics ×1
iterator ×1
make-shared ×1
nasm ×1
shared-ptr ×1
templates ×1