小编A. *_* S.的帖子

为什么覆盖全局新运算符和类特定运算符不是模糊行为?

请考虑以下代码:

class Foo 
{
public:
    //class-specific
    Foo operator+(Foo& rhs)
    {
       return Foo(); //Just return a temporary
    }

    void* operator new(size_t sd)
    {
        return malloc(sd);
    }
};

//global
Foo operator+(Foo& lhs, Foo& rhs)
{
    return Foo();
}

void* operator new(size_t sd)
{
    return malloc(sd);
}
Run Code Online (Sandbox Code Playgroud)

此代码将无法编译,说明调用不明确,因为它匹配两个运算符:

Foo a, b;
a + b;
Run Code Online (Sandbox Code Playgroud)

但是这个带有new运算符的编译器很好,并且会调用特定于类的运算符.

Foo* a = new Foo();
Run Code Online (Sandbox Code Playgroud)

为什么不导致编译错误?编译器是否以不同方式处理新运算符?(任何对标准的引用都将不胜感激.)

c++ new-operator language-lawyer c++11 c++14

10
推荐指数
2
解决办法
727
查看次数

为什么这种直接初始化有效?(C++ 17)

考虑以下两个类:

class B
{
public:
   B() { }
   B(const B& b) = delete; //Move ctor not implicitly declared
};


class A
{
public:
   A() { }

   operator B()
   {
       return B();
   }
};
Run Code Online (Sandbox Code Playgroud)

我可以看到为什么这段代码编译得很好:

A a;
B b = a;
Run Code Online (Sandbox Code Playgroud)

遵循复制初始化的规则,对象"a"被转换为类型B的prvalue,因为在C++ 17中不再需要复制构造函数,所以没有错误:

如果T是类类型,并且其他类型的cv-nonqualified版本不是T或从T派生,或者如果T是非类型类型,但是other的类型是类类型,则是用户定义的转换序列可以检查从其他类型转换为T(或从T派生的类型,如果T是类类型并且转换函数可用),并通过重载决策选择最佳的类型.转换的结果,即prvalue临时(直到C++ 17)prvalue表达式(自C++ 17),如果使用转换构造函数,则用于直接初始化对象.最后一步通常是优化的,转换的结果直接在为目标对象分配的内存中构造,但是即使没有使用,也需要访问适当的构造函数(移动或复制).(直到C++ 17)

但是为什么这个直接列表初始化编译呢?

A a;
B b{ a };
Run Code Online (Sandbox Code Playgroud)

我在列表初始化中找不到任何措辞,说明编译器在这种情况下应该尝试将A转换为B. 只考虑构造函数的重载决策:

如果前一阶段没有产生匹配,则T的所有构造函数都参与对由braced-init-list元素组成的参数集的重载解析,并限制只允许非缩小转换

但是在这种情况下,复制构造函数被删除,所以不应该通过重载决策来选择它吗?

c++ initialization language-lawyer c++17

6
推荐指数
1
解决办法
293
查看次数

为什么 LOCK 是 x86 上的完整屏障?

为什么LOCK前缀会导致 x86 上的完全障碍?(因此它耗尽了存储缓冲区并具有顺序一致性)

对于LOCK/read-modify-write 操作,不需要完全屏障,对缓存行的独占访问似乎就足够了。这是设计选择还是有其他限制?

x86 cpu-architecture memory-barriers

6
推荐指数
1
解决办法
380
查看次数

为什么要将全局偏移表用于共享库本身中定义的符号?

考虑以下简单的共享库源代码:

library.cpp:

static int global = 10;

int foo()
{
    return global;
}
Run Code Online (Sandbox Code Playgroud)

-fPICclang中的option 编译,它会导致以下对象汇编(x86-64):

foo(): # @foo()
  push rbp
  mov rbp, rsp
  mov eax, dword ptr [rip + global]
  pop rbp
  ret
global:
  .long 10 # 0xa
Run Code Online (Sandbox Code Playgroud)

由于符号是在库中定义的,因此编译器按预期使用PC相对地址: mov eax, dword ptr [rip + global]

但是,如果我们更改static int global = 10;int global = 10;具有外部链接的符号,则结果汇编为:

foo(): # @foo()
  push rbp
  mov rbp, rsp
  mov rax, qword ptr [rip + global@GOTPCREL]
  mov eax, dword ptr [rax] …
Run Code Online (Sandbox Code Playgroud)

c++ assembly symbols dynamic-linking got

5
推荐指数
1
解决办法
377
查看次数

MESI 协议和 std::atomic - 它是否确保所有写入对其他线程立即可见?

关于std::atomic,C++11 标准规定,存储到原子变量将在“合理的时间内”对该变量的加载变得可见。

\n\n

从 29.3p13 开始:

\n\n
\n

实现应该使原子存储在合理的时间内对原子加载可见。

\n
\n\n

然而,我很想知道在处理基于 MESI 缓存一致性协议(x86、x86-64、ARM 等)的特定 CPU 架构时实际会发生什么。

\n\n

如果我对 MESI 协议的理解是正确的,那么一个核心总是会立即读取先前写入/正在由另一个核心写入的值,可能是通过窥探它。(因为写入值意味着发出 RFO 请求,这反过来会使其他缓存行无效)

\n\n

这是否意味着当一个线程 A 将一个值存储到 an 中时std::atomic,另一个连续对该原子进行加载的线程 B 实际上总是会观察到 A 在 MESI 架构上写入的新值?(假设没有其他线程正在对该原子执行操作)

\n\n

\xe2\x80\x9csuccessively\xe2\x80\x9d 我的意思是在线程 A 发出原子存储之后。(修改顺序已更新)

\n

c++ cpu-architecture memory-model stdatomic mesi

5
推荐指数
1
解决办法
1011
查看次数

仅测试rar存档上的密码

我正在尝试对rar存档进行暴力攻击,我需要密码检查尽可能快.我以这种方式从我的程序中调用rarlab的"unrar"命令行实用程序:

unrar t -p[password] archive.rar
Run Code Online (Sandbox Code Playgroud)

它有效,但速度极慢.存档中的加密文件大约300MB,unrar实用程序告诉我只有在测试整个文件大小后才会出现CRC错误(密码错误).(需要10-15秒)

有没有更快的方法来测试存档密码?

passwords rar brute-force

4
推荐指数
2
解决办法
6155
查看次数

存储缓冲区和重新排序缓冲区是否都用于推测指令?

我知道重新排序缓冲区可以用作推测执行需求的历史缓冲区,并且它还允许将寄存器重命名为 ROB 条目(以中断命名依赖项,作为寄存器重命名)。

在线阅读资源/手册,似乎存储缓冲区也用于推测执行。如果路径预测错误,ROB 是否足以丢弃值?

x86 cpu-architecture

1
推荐指数
1
解决办法
192
查看次数