直接来自http://herbsutter.com/2013/05/09/gotw-1-solution/
虽然widget w();对我来说很清楚,但我不知道下面的代码如何成为函数声明?
// same problem (gadget and doodad are types)
//
widget w( gadget(), doodad() ); // pitfall: not a variable declaration
Run Code Online (Sandbox Code Playgroud)
这怎么可能?
我读的意见终极版约在一周的香草萨特的大师virtual功能,终于看见他提这一点:
[...]"最终的使用是罕见的" - 嗯,他们有点.我不知道很多,在标准化过程中,Bjarne反复询问它解决的问题和应该使用的模式的例子,我不记得任何突出的主要问题.我唯一知道的是,如果你正在定义一个库模块(它还不是标准概念),那么使叶子类最终可以为编译器提供更多信息来虚拟化调用,因为知道库外的代码"进一步推导出来,但我不确定这些日子在整个计划优化(包括积极的虚拟化)的存在下有多重要.
这个答案没有提供很多final关于课程用例的例子,我很想知道它可以解决哪些问题.你知道吗,或者final课堂上只会变成一些模糊不清且几乎未使用过的功能?
在Herb Sutter中When Is a Container Not a Container?,他展示了一个将指针放入容器的示例:
// Example 1: Is this code valid? safe? good?
//
vector<char> v;
// ...
char* p = &v[0];
// ... do something with *p ...
Run Code Online (Sandbox Code Playgroud)
然后跟着它"改进":
// Example 1(b): An improvement
// (when it's possible)
//
vector<char> v;
// ...
vector<char>::iterator i = v.begin();
// ... do something with *i ...
Run Code Online (Sandbox Code Playgroud)
但实际上并没有提供令人信服的论据:
一般来说,当你想指向一个容器内的对象时,更喜欢使用迭代器而不是指针并不是一个糟糕的指导.毕竟,迭代器在与指针大致相同的时间和相同的方式上无效,并且迭代器存在的一个原因是提供一种"指向"包含对象的方法.因此,如果您有选择,请更喜欢将迭代器用于容器中.
不幸的是,你不能总是得到与迭代器相同的效果,你可以使用指针到容器.迭代器方法有两个主要的潜在缺点,当适用时我们必须继续使用指针:
您不能总是方便地使用可以使用指针的迭代器.(见下面的例子.)
在迭代器是一个对象而不仅仅是一个光头指针的情况下,使用迭代器可能会产生额外的空间和性能开销.
在向量的情况下,迭代器只是一个RandomAccessIterator.对于所有意图和目的,这是指针上的薄包装.一种实现甚至承认这一点:
// This iterator adapter is 'normal' in the sense that it does not …Run Code Online (Sandbox Code Playgroud) 首先阅读Herb's Sutters GotW关于C++ 11中pimpl的帖子:
我在理解GotW#101中提出的解决方案时遇到了一些麻烦.据我所知,在GotW#100中辛苦解决的所有问题都复仇了:
的pimpl成员是外的线的模板,并且定义并不在使用点可见(在class widget的类定义和隐式生成的特殊成员函数widget).也没有任何明确的实例化.这将导致链接期间未解决的外部错误.
widget::impl在实例化定义的点上仍然是不完整的(我认为它实际上根本没有pimpl<widget::impl>::~pimpl()被实例化,只是被引用).因此std::unique_ptr<widget::impl>::~unique_ptr()调用delete指向不完整类型的指针,如果widget::impl有一个非平凡的析构函数,则会产生未定义的行为.
请解释是什么迫使编译器在widget::impl完成的上下文中生成特殊成员.因为我看不出它是如何工作的.
如果GotW#101仍然需要widget::~widget()在实现文件中明确定义,哪里widget::impl完成,那么请解释"更健壮"的评论(@sehe在他的答案中引用).
我看的GotW#101的核心要求是,包装"消除样板的一些作品",这在我看来(基于该段的其余部分)来表示的widget::~widget()声明和定义.所以请不要依赖于你的答案,在GotW#101中,那已经消失了!
Herb,如果你停下来,请告诉我是否可以在这里剪切+粘贴解决方案代码以供参考.
在GotW 94中,Herb Sutter区分了"经典C++"声明
const char* s = "Hello";
Run Code Online (Sandbox Code Playgroud)
和"现代"风格
auto s = "Hello";
Run Code Online (Sandbox Code Playgroud)
他告诉我们,有一个"中的类型细微的差别s,这里的auto风格是比较正确的." [编辑补充:评论表明,这可能不是Sutter实际意义的公平表示; 见下面的讨论.]
但是......有什么区别?我的印象是a const char *是引用字符串文字的正确方法.此外,当我问我的调试器(lldb)时,它似乎认为类型实际上是相同的:
* thread #1: tid = 0x1756c2, 0x0000000100000f8f test`main + 31 at test.cc:4, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f8f test`main + 31 at test.cc:4
1 int main(void) {
2 const char* s = "Hello";
3 auto t = "Hello";
-> 4 return 0;
5 }
(lldb) fr v
(const …Run Code Online (Sandbox Code Playgroud) 最近,我正在阅读帖子:Herb Sutter对GOTW的双重或无效 我对以下程序的解释有点困惑:
int main()
{
double x = 1e8;
while( x > 0 )
{
--x;
}
}
Run Code Online (Sandbox Code Playgroud)
假设此代码在某台机器上运行1秒.我同意这样的代码是愚蠢的.
然而,每样,如果我们改变问题的解释x从float到double,那么在某些编译器,它会继续运行永远计算机.该解释基于该标准的以下引用.
引用C++标准的3.9.1/8节:
有三种浮点类型:float,double和long double.double类型提供至少与float一样多的精度,long double类型提供至少与double一样多的精度.float类型的值集是double类型的值集的子集; double类型的值集是long double类型的值集的子集.
代码的问题是:
如果你将"double"改为"float",你会期望它需要多长时间?为什么?
这是给出的解释:
它可能需要大约1秒(在特定实现上,浮点数可能稍微快一些,或者比双精度快一些,或者稍微慢一些),或者永远,这取决于浮点数是否可以精确地表示从0到1e8(包括0和1e8)的所有整数值.
标准的上述引用意味着可能存在可以用double表示但不能用float表示的值.特别是,在一些流行的平台和编译器中,double可以精确地表示[0,1e8]中的所有整数值,但float不能.
如果float不能准确表示0到1e8之间的所有整数值,该怎么办?然后修改后的程序将开始倒计时,但最终会达到无法表示的值N和N-1 == N(由于浮点精度不足)......
我的问题是:
如果float甚至不能表示1e8,那么当我们初始化时我们应该已经溢出float x = 1e8; 那怎么会让电脑永远运转呢?
我在这里尝试了一个简单的例子(虽然不是double但是int)
#include <iostream>
int main()
{
int a = 4444444444444444444;
std::cout << "a " << a << std::endl;
return 0;
}
It outputs: a …Run Code Online (Sandbox Code Playgroud) http://www.gotw.ca/gotw/067.htm中有一个例子
int main()
{
double x = 1e8;
//float x = 1e8;
while( x > 0 )
{
--x;
}
}
Run Code Online (Sandbox Code Playgroud)
当你将double改为float时,它在VS2008中是一个无限循环.根据Gotw的解释:
如果float不能准确表示0到1e8之间的所有整数值,该怎么办?然后修改后的程序将开始倒计时,但最终将达到无法表示的值N和N-1 == N(由于浮点精度不足)......然后循环将保持卡住状态在该值上,直到运行程序的机器耗尽电量.
根据我的理解,IEEE754浮点数是单精度(32位),浮点数范围应为+/- 3.4e +/- 38,它应该有7位数字.
但我仍然不明白这究竟是怎么发生的:"最终达到一个无法表示的值N和N-1 == N(由于浮点精度不足)." 有人可以尝试解释这一点吗?
一些额外的信息:当我使用双x = 1e8时,它在大约1秒内完成,当我将其更改为浮动x = 1e8时,它运行的时间更长(5分钟后仍然运行),如果我将其更改为float x = 1e7;,它在大约1秒钟内完成.
我的测试环境是VS2008.
顺便说一句,我不是要求基本的IEEE 754格式解释,因为我已经明白了.
谢谢
取自:http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/
我们为什么要写:
auto pb = unique_ptr<base>{ make_unique<derived>() };
Run Code Online (Sandbox Code Playgroud)
而不仅仅是:
auto pb = make_unique<derived>();
Run Code Online (Sandbox Code Playgroud)
我唯一的猜测是,如果我们想要auto,我们需要帮助它推断出正确的类型(base这里).
如果是这样,那么对我来说,这将是真正值得怀疑的优点..键入auto然后在右侧输入很多初始化=..
我错过了什么?
参考HerbSutter的文章Gotw 54,他解释说
正确的"收缩适合"矢量或deque和
完全清除矢量或双端队列的正确方法
我们可以使用
container.resize()和container.clear()执行上述任务,还是我错过了什么?
草药萨特:
有效并发:使用锁定层次结构来避免死锁有效并发:打破Amdahl定律!»想要#88:候选人对于"最重要的常规"2008-01-01作者:Herb Sutter一位朋友最近问我下面的例子1是否合法,如果是的话是什么意思.它引发了一个很好的讨论,我想我会在这里发布.因为它已经接近GotW风格了,所以这些年后我还以为我会做另一个名誉......不,我没有做出新年决议来恢复写作常规的GotWs.:-)
JG问题Q1:以下代码是否合法C++?
Run Code Online (Sandbox Code Playgroud)// Example 1 string f() { return "abc"; } void g() { const string& s = f(); cout << s << endl; // can we still use the "temporary" object? }A1:是的.这是一个C++特性......代码是有效的,并且完全符合它的样子.
通常,临时对象仅持续到它出现的完整表达式的结尾.但是,C++故意指定将临时对象绑定到堆栈上对const的引用会延长临时对象生命周期的生命周期,从而避免了常见的悬空引用错误.在上面的示例中,f()返回的临时值一直持续到结束大括号.(注意,这仅适用于基于堆栈的引用.它不适用于作为对象成员的引用.)
最初,我认为最后一句意思是:
class A
{
public:
int x;
A(const int& x_)
{
x = x_;
}
};
int main()
{
A a(1); // assign lvalue to const int&
std::cout << a.x;
}
Run Code Online (Sandbox Code Playgroud)
但是,它显然很好用.
那么,"它对于作为对象成员的引用不起作用"是什么意思?