c++ - C++ std::map 中对值的要求?

标签 c++ stdmap

我声明了一个简单的结构以及默认构造函数、复制构造函数、赋值运算符和析构函数。但是,该结构不能用作 std::map 的值类型。

代码如下:

#include <string.h>
#include <iostream>
#include <string>
#include <map>

class Foo;
std::ostream & operator<<(std::ostream & os, const Foo & v);

typedef unsigned char BYTE;

struct Foo {
  char type_;        // char to label type
  size_t num_;       // number of elem, useful if array
  size_t total_;     // total memory
  BYTE * data_;      // content of memory

  Foo(const char * t) : type_('c'), num_(strlen(t)+1), total_(strlen(t)+1), data_(NULL) {
    data_ = new BYTE[total_];
    memcpy(data_, t, total_-1);
    ((char *)data_)[total_-1] = '\0';
  }

  Foo() : type_(), num_(), total_(), data_(NULL) {}

  Foo(const Foo& rhs) : type_(rhs.type_), num_(rhs.num_), total_(rhs.total_), data_(NULL) {
    if (total_) {
    data_ = new BYTE[total_];
    memcpy((char *)data_, (const char *)&rhs.data_, total_);
    }
  }

  Foo & operator=(const Foo& rhs) {
    if (&rhs != this) {
      releaseData();
      type_ = rhs.type_;
      num_ = rhs.num_;
      total_ = rhs.total_;
      data_ = new BYTE[total_];
      memcpy(data_, &rhs.data_, total_);
    }
    return *this;
  }

  ~Foo() {
    releaseData();
  }

private:
  void releaseData() {
    delete [] data_; data_ = NULL;
  }
};

inline std::ostream & operator<<(std::ostream & os, const Foo & v) {
  os << "(type: " << v.type_ << ", num: " << v.num_ << ", total: " << v.total_ << ", data: " << (const char *)v.data_ << ", data addr: " << (void *)v.data_ << ")";
  return os;
}


int main() {
  Foo c("/home/data/");
  std::map<std::string, Foo> store;
  store["abc"] = Foo("/home/data/");

  std::cout << c << std::endl;
  std::cout << store["abc"] << std::endl;
}

代码在使用 gcc 4.9.2 的 Linux 上编译。第一个打印正确打印出字符串,但第二个没有。

这段代码有什么问题?

最佳答案

您在复制构造函数和赋值运算符中对 memcpy() 的调用都是错误的。在这两种情况下,您都将 &rhs.data_ 指定为源:

memcpy((char *)data_, (const char *)&rhs.data_, total_);
...
memcpy(data_, &rhs.data_, total_);

通过以这种方式使用“&”,您将复制内存中紧跟在 data_ 成员之后的随机字节,不是 data_ 指向。

由于 data_ 已经是指向被复制数据的指针,您需要删除 & 并仅使用 rhs.data_ 作为-是(并且不需要类型转换):

memcpy(data_, rhs.data_, total_);

或者,摆脱所有这些手动逻辑,只使用 std::stringstd::vector,让编译器和 STL 处理所有为您进行内存管理和数据复制:

struct Foo {
  char type_;        // char to label type
  std::string data_; // content of memory

  Foo(const char * t) : type_('c'), data_(t) {}

  Foo() : type_() {}
};

inline std::ostream & operator<<(std::ostream & os, const Foo & v) {
  os << "(type: " << v.type_ << ", num: " << v.data_.length() << ", total: " << v.data_.capacity() << ", data: " << v.data_.c_str() << ", data addr: " << (void *)v.data_.data() << ")";
  return os;
}

struct Foo {
  char type_;        // char to label type
  std::vector<BYTE> data_; // content of memory

  Foo(const char * t) : type_('c') { std::copy(t, t+(strlen(t)+1), std::back_inserter(data_)); }

  Foo() : type_() {}
};

inline std::ostream & operator<<(std::ostream & os, const Foo & v) {
  os << "(type: " << v.type_ << ", num: " << v.data_.size() << ", total: " << v.data_.capacity() << ", data: " << (const char*) &v.data_[0] << ", data addr: " << (void *)&v.data_[0] << ")";
  return os;
}

关于c++ - C++ std::map 中对值的要求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29640547/

相关文章:

c++ - STL map Custom Key Class [默认构造函数]

c++ - 具有 char* 键和 int 值的容器

c++ - std::map::merge 的计算时间复杂度

c++ - std::min/std::max 作为模板比较器

c++ - Namespace or Class,只封装函数成员哪个更好

c++ - OpenCV:设置图像边框,无填充

c++ - 将自定义类型作为 map 的可能键的可能方法有哪些

c++ - 如何包含 draco_dec 库?

c++简单的while循环不循环

c++ - 如何在 std::map 中使用结构?