C++ 避免在c+中赋值的任何方法+;构造体?

C++ 避免在c+中赋值的任何方法+;构造体?,c++,constructor,C++,Constructor,我正在实现一个类请求,该类的构造函数将命令行作为其参数,该类的文件状态(如文件大小、上次修改时间等)作为其字段 我想给这些字段赋值,这涉及调用fstat(),访问struct stat中的值,并使用这些值 我知道C++构造函数中的赋值是不可接受的,应该使用初始化列表,但是我不知道如何在这些构造函数体中调用函数,而不使用构造函数体中的函数(使用括号)调用赋值操作符。 我该怎么办 如果我必须在构造函数体中初始化它们,我是否应该首先使用NULL初始化所有字段(我认为默认情况下会这样做) 类请求{ 向

我正在实现一个类
请求
,该类的构造函数将命令行作为其参数,该类的文件状态(如文件大小、上次修改时间等)作为其字段

我想给这些字段赋值,这涉及调用
fstat()
,访问
struct stat
中的值,并使用这些值

我知道C++构造函数中的赋值是不可接受的,应该使用初始化列表,但是我不知道如何在这些构造函数体中调用函数,而不使用构造函数体中的函数(使用括号)调用赋值操作符。 我该怎么办

如果我必须在构造函数体中初始化它们,我是否应该首先使用
NULL
初始化所有字段(我认为默认情况下会这样做)


类请求{
向量请求;
关闭内容长度;
字符*最后修改的字符;
公众:
显式请求(字符行[]):请求(拆分字符串(行)),内容长度(NULL),上次修改(NULL){
结构统计某人;
if(fstat(第[1]行,&sb)=-1){

cerr赋值本身没有问题。建议使用初始化列表的原因是,对于构造“昂贵”的成员,因为在构造函数体中赋值时,您需要支付两次费用:一次使用默认构造函数构造成员,然后将其赋值

因此,如果你有一个特殊的成员很难用简单的表达式初始化,不要为此而自暴自弃——在主体中初始化它。你可能想做的一件事是使它(即,该成员的)默认构造函数便宜,这将消除问题


这两种方法也有异常处理的含义,但我认为它们与您的情况无关。

分配本身没有问题。建议使用初始化列表的原因是针对“昂贵”的成员构造,因为如果在构造函数体中赋值,您需要支付两次:一次使用默认构造函数构造成员,然后将其赋值

因此,如果你有一个特殊的成员很难用简单的表达式初始化,不要为此而自暴自弃——在主体中初始化它。你可能想做的一件事是使它(即,该成员的)默认构造函数便宜,这将消除问题


这两种方法也有异常处理的含义,但我认为它们与您的情况无关。

使用成员初始化列表与构造函数中的赋值相比有两个优点:

  • 带有构造函数的成员变量只构造一次
  • 这是初始化
    const
    成员的唯一方法
但是,如果初始化太复杂而无法在构造函数中进行,那么在主体中初始化没有什么错

默认情况下,成员未初始化为NULL。具有构造函数(即非POD类型)的成员变量默认初始化,但仅此而已

执行复杂初始化并仍在初始值设定项列表中执行的一种方法是使用helper函数

Example::Example()
  : file_size_(CalculateFileSize())
{
};

int Example::CalculateFileSize()
{
  // Complex initialization here.
  // Be careful - this instance isn't fully initialized yet.
}

这种方法通常不像在构造函数体中那样清晰,因此我只建议在您确实需要在初始值设定项列表中执行所有操作时使用它(例如,如果您使用
const
成员变量)。还请注意,一次只能干净地使用它初始化一个成员变量。

使用成员初始化列表与构造函数中的赋值相比有两个优点:

  • 带有构造函数的成员变量只构造一次
  • 这是初始化
    const
    成员的唯一方法
但是,如果初始化太复杂而无法在构造函数中进行,那么在主体中初始化没有什么错

默认情况下,成员未初始化为NULL。具有构造函数(即非POD类型)的成员变量默认初始化,但仅此而已

执行复杂初始化并仍在初始值设定项列表中执行的一种方法是使用helper函数

Example::Example()
  : file_size_(CalculateFileSize())
{
};

int Example::CalculateFileSize()
{
  // Complex initialization here.
  // Be careful - this instance isn't fully initialized yet.
}

这种方法通常不像在构造函数体中那样清晰,因此我只建议在您确实需要在初始值设定项列表中执行所有操作时使用它(例如,如果您使用
const
成员变量)。还请注意,一次只能使用它来初始化一个成员变量。

构造函数体没有问题,特别是在程序中允许异常的情况下。这里更重要的规则是RAII

我会做如下的事情:

class request
{
  public:
    request (int fildes)
      : size(0)
      , last_modified_time(EPOCH)
    {
      struct stat statistics;
      auto error = fstat(&statistics);

      if (not error) {
          size = statistics.st_size;
          last_modified_time = statistics.st_mtimespec;
          // ...
      } else {
          // Note: if exceptions are not okay for you, then you need to move this
          // entire body to an Initialize() function that returns an error
          // indicator. This pattern is called two-phase initialization.
          //
          throw std::runtime_error("Hard disk is broken?!");
      }
    }
}

构造函数体没有错,特别是在程序中允许异常的情况下。这里更重要的规则是RAII

我会做如下的事情:

class request
{
  public:
    request (int fildes)
      : size(0)
      , last_modified_time(EPOCH)
    {
      struct stat statistics;
      auto error = fstat(&statistics);

      if (not error) {
          size = statistics.st_size;
          last_modified_time = statistics.st_mtimespec;
          // ...
      } else {
          // Note: if exceptions are not okay for you, then you need to move this
          // entire body to an Initialize() function that returns an error
          // indicator. This pattern is called two-phase initialization.
          //
          throw std::runtime_error("Hard disk is broken?!");
      }
    }
}

在主体中初始化它们,这是有原因的。是的,您可以先用NULL初始化字段,然后将其分配给另一个帮助函数中的值。在构造函数中尽可能少地做一些事情是一种好的方式。最好在ctor主体中发布使用赋值的代码,并征求改进意见不要使用直接初始化。坦率地说,对于诸如文件大小和上次修改时间之类的事情,在ctor主体中赋值可能没有问题,因为这些可能是内置类型(或接近它)。此外,请记住诸如“不要在ctor中赋值”之类的规则可以用合理的理由来打破。我不会担心。除非这是在时间关键型操作中大量使用的代码,否则差别很小。专注于编写您熟悉的工作、健壮、可读的代码。在正文中初始化它们,