避免不必要的临时分配,r值析构函数

时间:2017-01-12 15:27:46

标签: c++ c++11 rvalue

我有很多很多字符串,几乎从未在创建后修改过,对它们的访问时间并不是真正的问题。我必须尽可能减少内存使用量,所以我选择编写一个类而不是使用std::string,它必须保存额外的数据,如容量和长度,以符合标准。此更改导致内存使用量减少〜%30。

为了实现这一点,我编写了一个类,在内部包装C风格的以null结尾的字符串并管理缓冲区,因此该类只包含一个指针数据成员,它提供了足够的接口,很少访问和使用它,如{ {1}}。

我希望避免使用样板代码,并允许从std::stringstd::string进行透明转换。那么我是否可以避免在边缘情况下从std::string分配/复制数据,例如何时需要临时?考虑一下:

std::string

现在在以下代码中:

class A {
public:
  A(const char* p) : p_{std::strdup(p)} { }
  ~A() { free(p_); }

  A& append(const A&);

private:
  char* p_;
};

将创建临时对象,分配和复制数据。然后它会立即被摧毁。问题是,有没有办法避免这种情况,而不创建A a; a.append("test"); 等每个函数的版本。我还想支持A& append(const char*)的透明转换,因此它会自动成为每个函数的3个版本。

以下方法会产生什么影响:

std::string

如果这不起作用,我可以采用什么策略来解决这个问题?

2 个答案:

答案 0 :(得分:1)

  

以下方法会产生什么影响:

A(const char* p) &&
~A() &&

最可能的影响是编译错误,因为标准不允许在c / d-tor上使用ref-qualifiers。

我建议像字符串一样实现A::c_str,并使用模板中的以下帮助器:

template<class Str>
const char* c_str_help(const Str& str) {
    return str.c_str();
}
const char* c_str_help(const char* str) {
    return str;
}

class A {
  // ...

  const char* c_str() const { return p_; }

  template<class Str>
  A& append(const Str& str) {
      const char* s = c_str_help(str);
      // implement using const char* s
  }
};

PS:我建议使用unique_ptr<char, void(*)(void*)>而不是裸指针,以便更容易实现。

答案 1 :(得分:1)

有点类似于user2079303的方法,使用SFINAE,因此我们不会阻碍重载解析:

namespace detail_A {
    char const *getString(std::string const &str) {
        return str.c_str();
    }

    char const *getString(char const *str) {
        return str;
    }

    // More `getString`s as needed...

    template <class T>
    using enableString = decltype(getString(std::declval<T>()));
}

class A {
// ...

    template <class T, class = detail_A::enableString<T>>
    A &append(T const &str) {
        char const *p = detail_A::getString(str);

        std::cout << "Appending \"" << p << "\"\n";

        return *this;
    }
};

See it live on Coliru