标签: effective-c++

有效的C++仍然有效吗?

从我在这篇文章中看到的内容,我决定开始阅读Effective C++这本书.

但是现在由于C++ 11而有许多新功能,并且一些好的实践发生了变化,我不确定它是否真的是一个好主意.C++ 11的出现是否弃用了Effective C++中包含的任何建议?如果是这样,我应该避免哪些主题?

c++ coding-style effective-c++ c++11

134
推荐指数
3
解决办法
6万
查看次数

为什么argc不是常数?

int main( const int argc , const char[] const argv)
Run Code Online (Sandbox Code Playgroud)

正如有效的C++第3项规定"尽可能使用const",我开始思考"为什么不制作这些'常数'参数const"?

是否存在argc在程序中修改值的任何情况?

c++ program-entry-point const effective-c++ argc

102
推荐指数
4
解决办法
6538
查看次数

为什么我更喜欢明确给出类型的"显式类型化初始化器"习惯用法

我最近从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 …

c++ effective-c++ c++11

43
推荐指数
3
解决办法
2233
查看次数

C++在空类中编写和调用的函数是什么?

Effective C++一书中,我看到了以下段落:

结果,如果你写

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;
Run Code Online (Sandbox Code Playgroud)

但是在拆解通过编译上面的代码创建的可执行文件之后,我意识到并非如此:没有任何函数被调用.

这是主要的汇编代码:

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++ default-constructor effective-c++ empty-class

43
推荐指数
3
解决办法
3287
查看次数

有效的C++项目23首选非成员非友元函数到成员函数

虽然对类设计中的一些事实感到困惑,特别是函数是否应该是成员,但我查看了有效的c ++并找到了第23项,即将非成员非友元函数更喜欢成员函数.第一手阅读Web浏览器示例有一定意义,但是该示例中的便捷函数(在本书中命名为非成员函数)会改变类的状态,不是吗?

  • 所以,第一个问题,他们不应该成为会员吗?

  • 进一步阅读,他认为STL函数,实际上某些类没有实现的函数是在stl中实现的.继他们演变成被包装到一些合理的命名空间,如一些便利功能,这本书的想法std::sort,std::copyalgorithm.例如,vector类没有sort函数,并且使用stl sort函数,因此它不是向量类的成员.但是也可以将相同的推理延伸到向量类中的某些其他函数,例如,assign这样也不能作为成员实现,而是作为便利函数实现.但是,这也会改变对象的内部状态,例如它操作的排序.那么这个微妙但重要(我猜)问题背后的理由是什么呢?

如果你有权访问这本书,你可以为我澄清这些要点吗?

c++ encapsulation member-functions effective-c++ non-member-functions

35
推荐指数
4
解决办法
1万
查看次数

有效的C++:阻止受保护的继承?

我正在阅读Scott Meyers的Effective C++(第三版),在第32项的一段中:确保公共继承是第151页的"is-a",他发表了评论(我以粗体显示):

这仅适用于公共继承.只有当Student公开派生于Person时,C++才会表现得如我所描述的那样.私有继承意味着完全不同的东西(见第39项),受保护的继承是我今天的意义所在.

问题是:我该如何解释这个评论?迈耶斯试图传达受保护的遗产很少被认为是有用的,应该避免吗?

(我已经阅读了私有,公共和受保护的继承以及C++ FAQ Lite的私有和受保护的继承部分之间区别问题,这两个部分都解释了受保护的继承意味着什么,但是没有让我深入了解何时或为什么它会有用.)

c++ inheritance effective-c++

22
推荐指数
2
解决办法
3697
查看次数

为什么在Effective C++中以这种方式定义声明和定义?

有效的C++(第3版),第2项(身高const,enuminline#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积分常数不需要定义?
  • 为什么第二个代码片段在没有定义值时被认为是一个定义,但是包含该值的类中的声明仍然不是一个(基本上回到我的第一个问题)?
  • 是不是初始化定义?为什么这里没有违反"唯一定义"规则?

有可能我现在只是在这里混淆自己,所以有人可以从头开始重新教育我:为什么这两行代码声明和定义而不是另一行,那里有任何初始化实例吗?初始化也是定义吗?

信用:代码片段直接从本书中引用.

编辑:附加参考定义和声明之间的区别是什么? …

c++ effective-c++

21
推荐指数
3
解决办法
1114
查看次数

为什么static_cast(*this)到基类创建临时副本?

我正在阅读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(上面的代码)创建一个新副本?为什么不只是使用对象的基类部分?

c++ casting effective-c++

20
推荐指数
2
解决办法
5149
查看次数

是否适合在头文件中将值设置为"const char*"

我见过人们使用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)
  1. 方法1在某种程度上是错误的吗?
  2. 两者有什么区别 ?
  3. 我理解" const char * const var"和" const char * var" 之间的区别.如果在上面的方法中,如果const char * const var在方法1中声明和定义标题中的" "是否有意义?

c++ const-char effective-c++

15
推荐指数
3
解决办法
2万
查看次数

有效的C++"35.最小化文件之间的编译依赖性".它今天仍然有效吗?

在本章中,Scott Meyer提到了一些避免头文件依赖性的技术.主要目标是避免在更改仅限于其他包含的头文件时重新编译cpp文件.

我的问题是:

  • 在我过去的项目中,我从未关注过这条规则.编译时间不短,但不能容忍.它可能与我的项目的规模(或缺乏)有关.鉴于编译器技术的进步(例如clang),今天的技巧有多实用?

  • 我在哪里可以找到更多使用这种技术的例子?(例如Gnome或其他OSS项目)

PS我正在使用第2版.

c++ dependencies header effective-c++

14
推荐指数
2
解决办法
1821
查看次数