C++ POD初始化 我已经阅读了C++中的POD对象。我想把一个POD结构写入一个文件。因此,它应该只有公共数据,没有系数/dtor等,但据我所知,它可以有静态功能。那么我可以在这里使用命名构造函数习惯用法吗?我需要动态初始化,但我不想在每次结构初始化时重复参数检查 这是一个简单的例子,它只是一个简单的例子,不是一个工作代码: struct A { int day; int mouth; int year; static A MakeA(const int day, const int month, const int year) { // some simple arguments chech if ( !(day >= 1 && day <= 31) || !(month >=1 && month <=12) || !(year <= 2010) ) throw std::exception(); A result; result.day = day; result.month = month; result.year = year; return result; } };

C++ POD初始化 我已经阅读了C++中的POD对象。我想把一个POD结构写入一个文件。因此,它应该只有公共数据,没有系数/dtor等,但据我所知,它可以有静态功能。那么我可以在这里使用命名构造函数习惯用法吗?我需要动态初始化,但我不想在每次结构初始化时重复参数检查 这是一个简单的例子,它只是一个简单的例子,不是一个工作代码: struct A { int day; int mouth; int year; static A MakeA(const int day, const int month, const int year) { // some simple arguments chech if ( !(day >= 1 && day <= 31) || !(month >=1 && month <=12) || !(year <= 2010) ) throw std::exception(); A result; result.day = day; result.month = month; result.year = year; return result; } };,c++,C++,所以我有一个构造函数和一个POD结构,我可以简单地写入一个文件?正确吗?应该可以 您甚至可以拥有非静态成员函数,只要它们不是虚拟的 不能有像ctor/dtor这样自动调用的对象。你明确称之为的东西是好的。应该是好的 您甚至可以拥有非静态成员函数,只要它们不是虚拟的 不能有像ctor/dtor这样自动调用的对象。您显式调用的东西很好。如果您编写流操作符,它会使生活简单得多。 这并不是说用二进制编写要快得多,因为您需要编写代码来转换为不同的endian格式,而现在的空间实际上是无关紧要的 struc

所以我有一个构造函数和一个POD结构,我可以简单地写入一个文件?正确吗?

应该可以

您甚至可以拥有非静态成员函数,只要它们不是虚拟的

不能有像ctor/dtor这样自动调用的对象。你明确称之为的东西是好的。

应该是好的

您甚至可以拥有非静态成员函数,只要它们不是虚拟的


不能有像ctor/dtor这样自动调用的对象。您显式调用的东西很好。

如果您编写流操作符,它会使生活简单得多。 这并不是说用二进制编写要快得多,因为您需要编写代码来转换为不同的endian格式,而现在的空间实际上是无关紧要的

struct A
{
  int day;
  int mouth;
  int year;

   A(const int day, const int month, const int year)
   {  
      // some simple arguments chech
      if ( !(day >= 1 && day <= 31) || !(month >=1 && month <=12) || !(year <= 2010) )
         throw std::exception();

      this->day    = day;
      this->month  = month;
      this->year   = year;
   }
};
std::ostream& operator<<(std::ostream& str, A const& data)
{
    return str << data.day << " " << data.month << " " << data.year << " ";
}
std::istream& operator>>(std::istream& str,A& data)
{
    return str >> data.day >> data.month >> data.year;
}
有了这一定义,所有标准算法都变得可用且易于使用

int main()
{
    std::vector<A>    allDates;
    // Fill allDates with some dates.

    // copy dates from a file:
    std::ifstream  history("plop");
    std::copy(std::istream_iterator<A>(history),
              std::istream_iterator<A>(),
              std::back_inserter(allDates)
             );

    // Now  save a set of dates to a file:
    std::ofstream  history("plop2");
    std::copy(allDates.begin(),
              allDates.end(),
              std::ostream_iterator<A>(history)
             );
}

如果你编写流操作符,它会使生活简单得多。 这并不是说用二进制编写要快得多,因为您需要编写代码来转换为不同的endian格式,而现在的空间实际上是无关紧要的

struct A
{
  int day;
  int mouth;
  int year;

   A(const int day, const int month, const int year)
   {  
      // some simple arguments chech
      if ( !(day >= 1 && day <= 31) || !(month >=1 && month <=12) || !(year <= 2010) )
         throw std::exception();

      this->day    = day;
      this->month  = month;
      this->year   = year;
   }
};
std::ostream& operator<<(std::ostream& str, A const& data)
{
    return str << data.day << " " << data.month << " " << data.year << " ";
}
std::istream& operator>>(std::istream& str,A& data)
{
    return str >> data.day >> data.month >> data.year;
}
有了这一定义,所有标准算法都变得可用且易于使用

int main()
{
    std::vector<A>    allDates;
    // Fill allDates with some dates.

    // copy dates from a file:
    std::ifstream  history("plop");
    std::copy(std::istream_iterator<A>(history),
              std::istream_iterator<A>(),
              std::back_inserter(allDates)
             );

    // Now  save a set of dates to a file:
    std::ofstream  history("plop2");
    std::copy(allDates.begin(),
              allDates.end(),
              std::ostream_iterator<A>(history)
             );
}

你说得对。那只是一份普通的旧数据。没有有趣的虚拟表指针或类似的东西

现在,我仍然不确定简单地使用fwrite将数据写入文件是否是一个好主意。如果执行fread的程序是使用最初用于编写fwrite的相同版本的编译器编写的,则可以执行此操作并重新加载数据。但如果您切换编译器、平台,有时甚至是版本,这可能会改变


我建议您做一些使数据结构持久化的工作。

您是对的。那只是一份普通的旧数据。没有有趣的虚拟表指针或类似的东西

现在,我仍然不确定简单地使用fwrite将数据写入文件是否是一个好主意。如果执行fread的程序是使用最初用于编写fwrite的相同版本的编译器编写的,则可以执行此操作并重新加载数据。但如果您切换编译器、平台,有时甚至是版本,这可能会改变


我建议您做一些使数据结构持久化的工作。

最好使用std::runtime\u error,然后您可以添加一条错误消息。为什么要将POD结构写入文件?这本质上是不可移植的。编写适当的流运算符要简单得多。包含除虚拟函数以外的任何类型的成员函数的结构或类仍然可以写入文件;我不明白你认为这有什么问题?只要它是“平面”复合数据类型,即没有指向类外数据的指针,也没有虚拟函数。普通成员函数不影响对象的“大小”或构成。pod结构中不能有任何构造函数,我希望有某种类型的构造函数。@f0b0s:您完全破坏了可移植性的含义:这不能简单地移植到其他体系结构,只要我不移植它,它是完全可移植的!。但无论如何,为什么?如果您只是将每个成员插入到流中,那么它是可移植的,并且不会对代码进行不必要的限制。另外,请查看Boost.Serialization。为了回答您的问题,是的,您有一个POD类型。最好使用std::runtime\u error,然后您可以添加一条错误消息。为什么要将POD结构写入文件?这本质上是不可移植的。编写适当的流运算符要简单得多。包含除虚拟函数以外的任何类型的成员函数的结构或类仍然可以写入文件;我不明白你认为这有什么问题?只要它是“平面”复合数据类型,即没有指向类外数据的指针,也没有虚拟函数。普通成员函数不影响对象的“大小”或构成。pod结构中不能有任何构造函数,我希望有某种类型的构造函数。@f0b0s:您完全破坏了可移植性的含义:这不能简单地移植到其他体系结构,只要我不移植它,它是完全可移植的!。但无论如何,为什么?如果您只是将每个成员插入到流中,那么它是可移植的,并且不会对代码进行不必要的限制。另外,请查看Boost.Serialization。还有answe
你的问题,是的,你有一个POD类型。我建议你可以有一个构造函数或析构函数。“我不确定这个问题。”Clifford说,“我们是从严格的形式意义上评估这个问题的。实际上,拥有一个构造函数不会有什么坏处。你仍然可以在上面使用memcpy。但从形式上讲,当你这样做的时候,你不能保证当你重新加载它时,你会再次得到相同的值。@Clifford:这取决于你是在写标准还是在写实现。在当前标准下,具有构造函数的类是非POD的,因此如果您希望POD保证字节对字节的副本是有效的对象,那么您就不能拥有构造函数。最重要的是什么?当前的实现您说得很对:仅仅存在构造函数实际上不会对对象的逐字节副本的有效性造成任何问题。显然,构造函数可以做一些事情,比如存储这些东西,这会导致问题,但它们很容易避免。@Steve,@Johannes:谢谢;我受过教育。在所有情况下,我都建议在任何情况下序列化/反序列化成员函数,即使在其他情况下是POD。然后该类可以以适当的方式处理其文件表示,并且在维护时不会引起任何意外,因为如果该类变成非POD,那么它可能会引起任何意外,但是序列化是独立的,没有进行相应的修改。我建议您可以使用构造函数或析构函数。“我不确定这个问题。”Clifford说,“我们是从严格的形式意义上评估这个问题的。实际上,拥有一个构造函数不会有什么坏处。你仍然可以在上面使用memcpy。但从形式上讲,当你这样做的时候,你不能保证当你重新加载它时,你会再次得到相同的值。@Clifford:这取决于你是在写标准还是在写实现。在当前标准下,具有构造函数的类是非POD的,因此如果您希望POD保证字节对字节的副本是有效的对象,那么您就不能拥有构造函数。最重要的是什么?当前的实现您说得很对:仅仅存在构造函数实际上不会对对象的逐字节副本的有效性造成任何问题。显然,构造函数可以做一些事情,比如存储这些东西,这会导致问题,但它们很容易避免。@Steve,@Johannes:谢谢;我受过教育。在所有情况下,我都建议在任何情况下序列化/反序列化成员函数,即使在其他情况下是POD。然后,该类可以以适当的方式处理其文件表示,并且在维护过程中不会引起任何意外,因为如果该类变成非POD,那么它可能会引起任何意外,但是序列化是独立的,没有进行相应的修改。我想看一看ASCII转换与几个简单的字节交换的速度比较。我打赌ASCII数据仍然要慢得多。事实上,确实如此:虽然空间可能非常便宜,但网络和磁盘IO带宽却不便宜。@Omnifarious:在这种情况下,您应该使用平台无关算法来打包数据,然后在另一端安全地解包。指出局部区域中可能存在的缺陷并不意味着你可以概括并说它太慢。将问题保留在自己的领域内;我很怀疑有什么理由担心这里的表现。它遵循同样的老准则:正确性高于性能。快速编写正确的代码很容易,而且很有效。@Omnifarious:我怀疑这是否有意义,因为它会变慢。但是速度上的差异将被其他更为昂贵的操作(如磁盘/网络延迟)所掩盖,而对于任何实际应用程序,您都不会注意到这些操作。@Omnifarious:这个论点已经在现实生活中消失了。磁盘带宽是一种读取带宽。但我同意网络带宽可能会在你们的讨论中发挥作用。但在流的基础上添加一个压缩层是很容易的,这样就可以将应用程序与实际使用的压缩分离,并在长期应用中提供更大的灵活性。使用二进制格式基本上是将您与压缩格式紧密耦合,因为它位于应用程序层。我希望看到ASCII转换与一些简单字节交换的速度比较。我打赌ASCII数据仍然要慢得多。事实上,确实如此:虽然空间可能非常便宜,但网络和磁盘IO带宽却不便宜。@Omnifarious:在这种情况下,您应该使用平台无关算法来打包数据,然后在另一端安全地解包。指出局部区域中可能存在的缺陷并不意味着你可以概括并说它太慢。将问题保留在自己的领域内;我很怀疑有什么理由担心这里的表现。它遵循同样的老准则:正确性高于性能。快速编写正确的代码很容易,而且很有效。@Omnifarious:我怀疑这是否有意义,因为它会变慢。但速度上的差异将被其他m所掩盖
uch对于任何实际应用程序来说都不会注意到的更昂贵的操作,如磁盘/网络延迟。@Omnifarious:这个论点已经在现实生活中消失了。磁盘带宽是一种读取带宽。但我同意网络带宽可能会在你们的讨论中发挥作用。但在流的基础上添加一个压缩层是很容易的,这样就可以将应用程序与实际使用的压缩分离,并在长期应用中提供更大的灵活性。使用二进制格式基本上与压缩格式紧密耦合,因为它位于应用程序层。