问题标签 [gotw]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
157 浏览

c++ - 仅在 Linux 上使用 clang 对 Pimpl 析构函数的未定义引用

受到GoTW 101的启发,我决定尝试将 Pimpl 习语应用到我正在使用那里描述的 pimpl 包装器的库的一部分。

但是,在尝试编译时,我得到了对该 Pimpl 类的析构函数的未定义引用。这只发生在 clang 上并且Linux 上发生。即,Linux 上的 GCC 和 OSX 上的 Clang 工作正常。

这是不起作用的代码:

头文件

源文件

任何想法都将不胜感激,这让我挠头了一段时间!

0 投票
1 回答
263 浏览

c++ - 如何在 CRTP 基类中根据“op=”实现“op”?

Herb Sutter 的第 4 周 Guru “Class Mechanics”教导说,重载运算符的“a op b”形式应该按照“a op= b”形式来实现(参见解决方案中的第 4 点) .

作为一个例子,他向操作员展示了如何做到这一点+

他指出,第一个参数 inoperator+是有意按值传递的,因此如果调用者传递一个临时参数,它可以被移动。

请注意,这要求operator+是非成员函数。

我的问题是,如何将此技术应用于CRTP基类中的重载运算符?

所以说这是我的 CRTP 基类,它有operator+=

如果我放弃“按值传递第一个参数”优化,我可以看到如何以成员函数的形式实现operator+operator+=

但是有没有办法在使用该优化时做到这一点(因此使operator+非成员)?

0 投票
2 回答
650 浏览

c++ - C++11 类型推导 vs const char *

GotW 94中,Herb Sutter 对“经典 C++”声明进行了区分

和“现代”风格

他告诉我们,“类型的细微差别,s风格auto更正确”。[编辑添加:评论表明这可能不能公平地代表萨特的实际意思;见下文讨论。]

但是……有什么区别?我的印象是 aconst char *是引用字符串文字的正确方法。此外,当我问我的调试器(lldb)时,似乎认为类型实际上是相同的:

萨特所指的细微差别在哪里?

0 投票
3 回答
2987 浏览

c++ - 对于向量,为什么更喜欢迭代器而不是指针?

在 Herb Sutter'sWhen Is a Container Not a Container?中,他展示了一个将指针放入容器的示例:

然后用“改进”跟进它:

但并没有真正提供一个令人信服的论点:

一般来说,当您想要指向容器内的对象时,更喜欢使用迭代器而不是指针并不是一个糟糕的指导方针。毕竟,迭代器在与指针几乎相同的时间和相同的方式下失效,迭代器存在的一个原因是提供一种“指向”包含对象的方法。所以,如果你有选择的话,更喜欢在容器中使用迭代器。

不幸的是,使用迭代器并不能总是获得与使用指向容器的指针相同的效果。迭代器方法有两个主要的潜在缺点,当任何一个适用时,我们都必须继续使用指针:

  1. 您不能总是方便地使用可以使用指针的迭代器。(见下面的例子。)

  2. 在迭代器是一个对象而不仅仅是一个光秃秃的指针的情况下,使用迭代器可能会产生额外的空间和性能开销。

在向量的情况下,迭代器只是一个 RandomAccessIterator。出于所有意图和目的,这是对指针的薄包装。一种实现甚至承认这一点:

_Iterator此外,该实现存储类型为pointeror的成员值T*。换句话说,只是一个指针。此外,difference_type这种类型的 isstd::ptrdiff_t和定义的操作只是简单的包装器(即operator++is ++_pointeroperator*is *_pointer)等等。

按照 Sutter 的论点,这个迭代器类对指针没有任何好处,只有缺点。我对么?

0 投票
2 回答
63 浏览

c++ - C++ IntAtomicGet、GotW 的原因

GotW 文章 #45中,Herb 声明如下:

这个 if 条件不是线程安全的。一方面,评估甚至“data_->refs > 1”可能不是原子的;如果是这样,如果线程 1 尝试评估“data_->refs > 1”,而线程 2 正在更新 refs 的值,则从 data_->refs 读取的值可能是任何值——1、2,甚至是其他值这既不是原始值也不是新值。

此外,他指出 data_->refs 可以在与 1 比较和与 Unshareable 比较之间进行修改。

再往下,我们找到了一个解决方案:

现在,我知道两个比较都使用了相同的 refs,解决了问题 2。但为什么是 IntAtomicGet?我在该主题的搜索中一无所获——所有原子操作都集中在读、修改、写操作上,在这里我们只是读一下。那我们能不能...

...最终可能只是一条指令?

0 投票
2 回答
1145 浏览

c++ - 为什么在使用 PIMPL 成语时这种类型不完整?

我使用的是 PIMPL 成语,特别是我使用的是这篇文章提供的模板。鉴于下面的一组类并使用 VS2015 Update 3 进行编译,我得到了编译错误:

错误 C2027 使用未定义类型“C::C_impl”(编译源文件 src\A.cpp)

错误 C2338 无法删除不完整的类型(编译源文件 src\A.cpp)

警告 C4150 删除指向不完整类型“C::C_impl”的指针;没有调用析构函数(编译源文件 src\A.cpp)

我可以通过取消注释来解决这个问题C::~C(),这让我相信某些东西正在阻止~C()自动生成,但我不明白是什么。根据此参考,如果以下任何一项为真,则类型 T 的析构函数被隐式定义为已删除:

  1. T 有一个不能被破坏的非静态数据成员(已删除或不可访问的析构函数)
  2. T 具有无法破坏的直接或虚拟基类(已删除或不可访问的析构函数)
  3. T 是一个联合,并且有一个带有非平凡析构函数的变体成员。
  4. 隐式声明的析构函数是虚拟的(因为基类有一个虚拟析构函数),并且查找释放函数(运算符 delete() 会导致调用模棱两可、已删除或不可访问的函数。

第 2、3 和 4 项显然不适用于C,而且我不认为第 1 项适用,因为pimpl<>(C的唯一成员) 明确定义了析构函数。

有人可以解释发生了什么吗?

溴化氢

通道

A.cpp

C.cpp

为了完整起见,上面引用的帖子中的 PIMPL 实现:

粉刺.h

PimplImpl.h

关于上面代码的几点说明:

  • 我正在尝试向我的图书馆的消费者公开AC保持B内部信息。
  • 这里没有B.cpp,它会是空的。
0 投票
1 回答
65 浏览

c++ - GotW #88 中的“它不适用于对象成员的引用”是什么意思?

草本萨特

有效并发:使用锁层次结构避免死锁有效并发:打破阿姆达尔定律!» GotW #88: A Candidate for the “Most Important const” 2008-01-01 作者 Herb Sutter 一位朋友最近问我下面的示例 1 是否合法,如果是,这意味着什么。它引发了一个很好的讨论,我想我会在这里发布。因为它已经接近 GotW 风格,所以我想我会在这么多年之后再做一个荣誉的……不,我还没有做出新年的决心来继续写普通的 GotW。:-)

JG Questions Q1: 下面的代码是合法的C++吗?

A1:是的。这是一个 C++ 特性……代码是有效的,并且完全按照它看起来要做的事情。

通常,临时对象只持续到它出现的完整表达式的结尾。但是,C++ 特意指定将临时对象绑定到堆栈上的 const 引用会将临时对象的生命周期延长到引用本身的生命周期,从而避免常见的悬空引用错误。在上面的示例中,由 f() 返回的临时值一直存在到右花括号为止。(请注意,这仅适用于基于堆栈的引用。它不适用于作为 objects 成员的引用。)

原来,我认为最后一句话的意思是:

但是,它显然工作正常。

那么,“它对对象成员的引用不起作用”是什么意思?