从我在这篇文章中看到的内容,我决定开始阅读Effective C++这本书.
但是现在由于C++ 11而有许多新功能,并且一些好的实践发生了变化,我不确定它是否真的是一个好主意.C++ 11的出现是否弃用了Effective C++中包含的任何建议?如果是这样,我应该避免哪些主题?
int main( const int argc , const char[] const argv)
Run Code Online (Sandbox Code Playgroud)
正如有效的C++第3项规定"尽可能使用const",我开始思考"为什么不制作这些'常数'参数const
"?
是否存在argc
在程序中修改值的任何情况?
我最近从Scott Meyers那里购买了新的Effective现代C++,现在正在阅读它.但是我遇到了一件事,这完全让我感到烦恼.
斯科特在第5项中说,使用auto
是一件好事.它可以节省打字,在大多数情况下会为您提供正确的类型,并且可能不会出现类型不匹配的情况.我完全理解这一点,并认为这也是auto
一件好事.
但是在第6项中斯科特告诉我,每枚硬币都有两面.同样可能存在一些情况,例如auto
推断完全错误的类型,例如代理对象.
您可能已经知道这个例子:
class Widget;
std::vector<bool> features(Widget w);
Widget w;
bool priority = features(w)[5]; // this is fine
auto priority = features(w)[5]; // this result in priority being a proxy
// to a temporary object, which will result
// in undefined behavior on usage after that
// line
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.
但斯科特对此的解决方案是所谓的"明确类型化的初始化器成语".这个想法是,在初始化器上使用static_cast,如下所示:
auto priority = static_cast<bool>(features(w)[5]);
Run Code Online (Sandbox Code Playgroud)
但这不仅会导致更多的输入,而且还会明确说明应该推断出的类型.你基本上失去了auto
超过明确给定类型的优点.
任何人都可以告诉我,为什么使用这个成语是有利的?
首先要澄清一下,我的问题旨在为什么要写:
auto priority = static_cast<bool>(features(w)[5]);
Run Code Online (Sandbox Code Playgroud)
代替:
bool priority = features(w)[5];
Run Code Online (Sandbox Code Playgroud)
@Sergey提出了一个关于GotW关于这个主题的好文章的链接,这部分回答了我的问题.
指南:考虑声明局部变量auto …
在Effective C++一书中,我看到了以下段落:
结果,如果你写
Run Code Online (Sandbox Code Playgroud)class Empty{};
它基本上和你写的一样:
Run Code Online (Sandbox Code Playgroud)class Empty { public: Empty() { ... } Empty(const Empty& rhs) { ... } ~Empty() { ... } Empty& operator=(const Empty& rhs) { ... } // copy assignment operator };
以下代码将导致生成每个函数:
Run Code Online (Sandbox Code Playgroud)Empty e1; Empty e2(e1); e2 = e1;
但是在拆解通过编译上面的代码创建的可执行文件之后,我意识到并非如此:没有任何函数被调用.
这是主要的汇编代码:
00000000004006cd <main>:
4006cd: 55 push %rbp
4006ce: 48 89 e5 mov %rsp,%rbp
4006d1: b8 00 00 00 00 mov $0x0,%eax
4006d6: 5d pop %rbp
4006d7: c3 retq
Run Code Online (Sandbox Code Playgroud)
段中没有任何名为"Empty"的函数.text
.
那么在我们调用构造函数或赋值空类之后,编译器的行为究竟是什么?这本书说它会产生一些功能吗?如果是这样,他们存放在哪里?
虽然对类设计中的一些事实感到困惑,特别是函数是否应该是成员,但我查看了有效的c ++并找到了第23项,即将非成员非友元函数更喜欢成员函数.第一手阅读Web浏览器示例有一定意义,但是该示例中的便捷函数(在本书中命名为非成员函数)会改变类的状态,不是吗?
所以,第一个问题,他们不应该成为会员吗?
进一步阅读,他认为STL函数,实际上某些类没有实现的函数是在stl中实现的.继他们演变成被包装到一些合理的命名空间,如一些便利功能,这本书的想法std::sort
,std::copy
从algorithm
.例如,vector
类没有sort
函数,并且使用stl sort
函数,因此它不是向量类的成员.但是也可以将相同的推理延伸到向量类中的某些其他函数,例如,assign
这样也不能作为成员实现,而是作为便利函数实现.但是,这也会改变对象的内部状态,例如它操作的排序.那么这个微妙但重要(我猜)问题背后的理由是什么呢?
如果你有权访问这本书,你可以为我澄清这些要点吗?
c++ encapsulation member-functions effective-c++ non-member-functions
我正在阅读Scott Meyers的Effective C++(第三版),在第32项的一段中:确保公共继承是第151页的"is-a",他发表了评论(我以粗体显示):
这仅适用于公共继承.只有当Student公开派生于Person时,C++才会表现得如我所描述的那样.私有继承意味着完全不同的东西(见第39项),受保护的继承是我今天的意义所在.
问题是:我该如何解释这个评论?迈耶斯试图传达受保护的遗产很少被认为是有用的,应该避免吗?
(我已经阅读了私有,公共和受保护的继承以及C++ FAQ Lite的私有和受保护的继承部分之间的 区别问题,这两个部分都解释了受保护的继承意味着什么,但是没有让我深入了解何时或为什么它会有用.)
在有效的C++(第3版),第2项(身高const
,enum
和inline
对#define
),为类特定常量代码段读:
class GamePlayer {
private:
static const int NumTurns = 5; // constant declaration
int scores[NumTurns]; // use of constant
...
};
Run Code Online (Sandbox Code Playgroud)
然后,本书(用我自己的话说)static const int NumTurns = 5;
不是一个定义,这通常是C++对类成员所要求的,除非它是一个从不使用地址的静态整数常量.如果上面的常量不是真的,或者编译器因任何原因坚持定义,那么定义应该在实现文件中提供如下:
const int GamePlayer::NumTurns; // definition of NumTurns; see
// below for why no value is given
Run Code Online (Sandbox Code Playgroud)
根据这本书(也用我自己的话说),定义中没有给出任何价值,因为它已在声明中给出.
这让我认为我已经知道的声明和定义的定义令人困惑(我在问这个问题之前在Google上仔细检查过):
static const int NumTurns = 5
不是定义?是NumTurns
不是初始化为5
这里的值,是不是当声明和定义一起出现时,它被称为初始化?static
积分常数不需要定义?有可能我现在只是在这里混淆自己,所以有人可以从头开始重新教育我:为什么这两行代码声明和定义而不是另一行,那里有任何初始化实例吗?初始化也是定义吗?
信用:代码片段直接从本书中引用.
编辑:附加参考定义和声明之间的区别是什么? …
我正在阅读Effective C++并遇到了这个例子:
class Window { // base class
public:
virtual void onResize() { ... } // base onResize impl
...
};
class SpecialWindow: public Window { // derived class
public:
virtual void onResize() { // derived onResize impl;
static_cast<Window>(*this).onResize(); // cast *this to Window,
// then call its onResize;
// this doesn't work!
... // do SpecialWindow-
} // specific stuff
...
};
Run Code Online (Sandbox Code Playgroud)
这本书说:
您可能没想到的是它不会在当前对象上调用该函数!相反,强制转换创建了*this的基类部分的新临时副本,然后在副本上调用onResize!
为什么static_cast(上面的代码)创建一个新副本?为什么不只是使用对象的基类部分?
我见过人们使用2种方法来声明和定义char *
.
Medhod 1:头文件如下
extern const char* COUNTRY_NAME_USA = "USA";
Run Code Online (Sandbox Code Playgroud)
Medhod 2:
头文件具有以下声明:
extern const char* COUNTRY_NAME_USA;
Run Code Online (Sandbox Code Playgroud)
cpp文件具有以下定义:
extern const char* COUNTRY_NAME_USA = "USA";
Run Code Online (Sandbox Code Playgroud)
const char * const var
"和" const char * var
" 之间的区别.如果在上面的方法中,如果const char * const var
在方法1中声明和定义标题中的" "是否有意义?在本章中,Scott Meyer提到了一些避免头文件依赖性的技术.主要目标是避免在更改仅限于其他包含的头文件时重新编译cpp文件.
我的问题是:
在我过去的项目中,我从未关注过这条规则.编译时间不短,但不能容忍.它可能与我的项目的规模(或缺乏)有关.鉴于编译器技术的进步(例如clang),今天的技巧有多实用?
我在哪里可以找到更多使用这种技术的例子?(例如Gnome或其他OSS项目)
PS我正在使用第2版.
c++ ×10
effective-c++ ×10
c++11 ×2
argc ×1
casting ×1
coding-style ×1
const ×1
const-char ×1
dependencies ×1
empty-class ×1
header ×1
inheritance ×1