问题标签 [effective-c++]

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 投票
1 回答
61 浏览

c++ - 了解关于 EMC++ 第 41 项的勘误表的评论

在 Item 41 中,Scott Meyers 编写了以下两个类:

评论中写的是正确的,即使这并不意味着这两种解决方案是等价的,并且书中确实讨论了一些差异。

然而,在勘误表中,作者评论了书中未讨论的另一个差异:

(1) 左值和右值的重载与 (2) 采用通用引用 (uref) 的模板之间的另一个行为差异是左值重载声明了它的参数const,而 uref 方法没有。这意味着在左值重载的参数上调用的函数将始终是const版本,而在 uref 版本的参数上调用的函数const只有在传入的参数是 时才是版本const。换句话说,非const左值参数可能会在重载设计与 uref 设计中产生不同的行为。

但我不确定我是否理解它。

实际上,写这个问题我可能已经理解了,但我没有写答案,因为我仍然不确定。

可能作者是说,当一个非const左值被传递给时addName,在第一个代码中,而在第二个代码中是非-,这意味着如果被传递给另一个函数(或调用了成员函数)该函数需要接受一个参数(或者是一个成员函数)newNameconstconstnewNameconstconst

我的解释是否正确?

但是,我看不出这在具体示例中有何不同,因为没有调用成员函数 on newName也没有将它传递给具有不同重载const和非const参数的函数(不完全是:std::vector<T>::push_back有两个const T&参数重载和T&&arguments`,但左值仍将仅绑定到前一个重载...)。

0 投票
1 回答
31 浏览

c++ - 关于不允许重复的容器的放置和插入效率不同的混淆

Effective Modern C++的第 41 条中,以下情况之一是使 emplacement 函数有机会比插入 conterparts 性能更高的情况之一:

容器不太可能拒绝新值作为重复项

原因是,给定试图插入容器的对象的构造函数的参数, emplace 函数将必须构造该对象以评估它是否已经存在于容器中,在这种情况下,构造是浪费,其次是破坏也不可避免的浪费。

我在这里已经有些疑问了。如果我要使用插入函数来避免这种情况,那么我将自己构造对象(可能是一个临时对象,将我传递给 emplacement 函数的参数传递给它的构造函数),并将其传递给插入函数,然后那个临时的,如果容器中已经有一个相等的值,就会被销毁。

所以我看不出有什么不同。

此外,作者补充说

此类节点是为就位功能创建的,而不是为插入功能创建的。

如果该对象已经在容器中,为什么我应该使用哪个函数将对象插入容器中?

0 投票
1 回答
73 浏览

c++ - emplacement 函数通过就地构造而不是通过赋值向容器添加新元素是什么意思?

Effective Modern C++的第 41 条中, Scott Meyers 提到了这种差异及其对插入效率的影响。

我对此有一些疑问,但在提出问题之前,我需要了解这两种添加元素的方式之间的区别是什么。

考虑书中的代码示例:

很明显,之后// adding some elements to vs,可能是

  • vs.capacity() == vs.size(), 或者
  • vs.capacity() > vs.size().

相应地,

  • vs必须重新分配,并且(在重新分配发生之前vs名为vs[0], , ... 的那些元素)中的所有预先存在的元素都必须移动构造到新的内存位置( , , ...的新位置)vs[1] vs[1]vs[2]
  • vs必须vs.resize(vs.size() + 1)并且所有预先存在的元素都必须移动分配给下一个索引,显然是向后处理,从最后一个元素到第一个元素。

(显然我提到了移动操作,因为std::string提供了noexcept移动操作。如果不是这种情况,那么上面的场景略有不同,将使用复制操作。)

然而,我的问题的症结所在,就在上面的代码之后,书上写着(我的斜体

[…]很少有实现会将添加std::string vs[0]. 相反,他们会将值移动分配到位。[…]

在完成房间以容纳新元素之后,这两种情况是什么?

  • 如果emplace通过移动赋值添加元素,这意味着它在v[0] = std::string{strarg};where strarg == "xyzzy",对吗?
  • 但是构造被 占据的元素的另一种情况是v[0]什么?是安置new吗?它会是什么样子?我想它应该类似于Placement new here部分的代码块,但我不确定在这种情况下它会是什么样子。
0 投票
1 回答
146 浏览

c++ - 递归 constexpr 函数

我正在阅读有效的现代 C++ 并想尝试使用 const 表达式的一个非常基本的函数。我的 C++ 技能真的不是很好,但我不知道这个基本代码有什么问题:

如评论中所述,如果我使用 return x == 43337,则此代码有效,但任何较大的值都会导致分段错误。

这段代码有什么问题?如果我正确理解了 const 表达式,则计算应该在编译时进行,但是在我看来,计算是在运行时进行的。较大的值似乎会导致分段错误,因为调用堆栈太深。

但是,我不确定为什么我没有收到任何编译器错误,因为计算应该在编译时进行(显然不是)。

此外,如果我的方法签名如下所示,此代码是否有效:

constexpr decltype(auto) test( int x )

0 投票
1 回答
66 浏览

c++ - 使用 std::make_shared 后可以缓存吗?

我正在阅读 Effective Modern C++ (Scott Meyers) 并尝试第 21 项中的一些内容。这本书说使用的副作用是在所有s 和s 都消失std::make_shared之前无法释放内存(因为控制块与内存一起分配)。shared_ptrweak_ptr

我预计这将意味着如果我保留一个缓存来保存一堆weak_ptrs,那么就不会释放任何内存。我使用下面的代码进行了尝试,但是由于从向量中删除了 shared_ptrs,我可以使用 pmap 看到实际上正在释放内存。谁能解释我哪里出错了?或者如果我的理解是错误的?

注:loadWidget本实验的目的与书中的功能不同。

0 投票
1 回答
155 浏览

c++ - Effective C++ (3rd edition) Item 4 代码布局

在 Scott Meyers 的Effective C++: 55 Specific Ways to Improvement Your Programs and Designs(第 3 版)中,他在第 4 项中描述了在不同翻译单元中定义的非本地静态对象的初始化如何崩溃,并提供了一堆示例代码。

但是,我对代码布局感到困惑,应该是什么?

我试过的:

  • fileSystem.h
  • fileSystem.cpp
  • directory.h
  • directory.cpp

而在执行g++ directory.cpp fileSystem.cpp的时候,结果是这样的:

#include对 C++ 中的内容有些不安,我希望它不会妨碍我理解有效 C++ 第 4 条中示例代码的正确布局。