【问题标题】:How to make char array and std::string "in a relationship"?如何使 char 数组和 std::string “建立关系”?
【发布时间】:2013-08-12 15:16:34
【问题描述】:

我正在寻找一种将 char 数组与字符串相关联的方法,以便每当 char 数组更改时,字符串也会更改。我试图将 char 数组和字符串变量都放在一个联合中,但这并没有像编译器抱怨的那样工作......

欢迎提出任何想法...

【问题讨论】:

  • 这听起来很像一个 XY 问题 - 也许正确的解决方案是根本不这样做?
  • 您可能需要实现一个 C 字符串包装类,该类必须在每次调用其上的方法时重新计算参数。它不会很有效,而且我想不出需要它的充分理由。我能问一下你为什么要找这样的东西吗?
  • 为什么需要将字符串作为 char 数组进行操作?我猜稍微重写一下,你可以只用 std::string 。
  • 这一切仅仅是为了获得std::string 的额外功能和大量会员功能,同时仍将原始数据暴露给您无法控制的世界吗?您是否至少认为您对未说出的原始问题的“解决方案”可能存在问题,因为解决方案本身是可疑的? (参见 Mats 的评论)。
  • 你应该只使用std::string。您可以通过c_str() 从中获取一个 c 字符串。您可以通过data() 直接访问缓冲区。它也是C++方式。拥抱变化:-)

标签: c++ arrays string char unions


【解决方案1】:
    class Observable_CharArray
    {
        char* arr;
        std::function<void(char*)> change_callback;

    public:
        Observable_CharArray(int size, std::function<void(char*)> callback)
        : arr(new char[size]), change_callback(callback){}

        ~Observable_CharArray()/*as mentioned by Hulk*/
        {
            delete[] arr;
        }

        void SetCallback(std::function<void(char*)> callback)
        {
            change_callback = callback;
        }

        /*other member function to give access to array*/

        void change_function()
        {
            //change the array here
            change_callback(arr);
        }

    };

    class Observer_String
    {
        std::string rep;

        void callback(char* cc)
        {
            rep = std::string(cc);
        }

     public:
        Observer_String(Observable_CharArray* och)
        {
            och->SetCallback(std::bind(&callback, this, _1));
        }

        /*other member functions to access rep*/
    };

设计绝对可以改进。 除了观察 char 数组之外,还有其他方法可以解决您的实际问题。

【讨论】:

  • 至少你错过了删除数组的析构函数。
  • (你并没有真正回答 OP 的问题)
  • 我错过了很多其他的东西......想展示创建可观察类的方法,我给出的代码有很大的改进空间。另外,我没有提供观察者的代码。
  • 您的答案应该清楚地说明您的 code-sn-p 试图演示的内容,并且它只是解决方案的一小部分。就现在的样子,怕是更糟没用了。因此,如果您想获得支持,最好编辑您的答案;-)
【解决方案2】:

问题在于 std::string 可能会更改内部的字符串数组(尤其是在调整大小时)。例如, c_str 返回当前字符串的地址 - 文档说“返回的指针可能会因进一步调用修改对象的其他成员函数而失效。”。

如果您确定不会调用字符串方法(因此字符串将保留在相同的内存位置),您可以尝试直接访问 c_str 指针(您的 char 数组)并修改其内容。

std::string str = "test";
char* arr = (char*)str.c_str();
arr[3] = 'a';

注意:除非在测试环境中,否则我强烈建议不要这样做。

换句话说,字符串类并不能保证它会留在内存中的相同位置——这意味着尝试通过 char 数组访问它是不可能的。

最好的方法是创建另一个字符串类,强制 char 数组始终保持相同的大小(因此可以一直保持在相同的内存位置)。您还可以创建一个更大的数组(例如最大大小的字符串)来应对任何字符串大小的变化——但这应该在您的包装类中强制执行。

【讨论】:

    【解决方案3】:

    可以这样做,但你不应该

    #include <iostream>
    #include <string>
    
    int main()
    {
       std::string test("123456789");
       std::cout << test << "\n";
       char* data = &test.front(); // use &(*test.begin()) for pre-C++11 code
       for ( size_t i(0); i < test.size(); ++i )
       {
          data[i] = 57 - i;
       }
       std::cout << test << "\n";
    }
    

    输出将是

    123456789
    987654321
    

    然而,这又是std::string 试图为您提供便利的一切。如果您使用data,则可能会导致UB,对test 的更改可能会使data 指向垃圾。

    【讨论】:

      【解决方案4】:

      你不应该这样做!

      但是,有很多(危险的)方法可以实现它:

      char* cStr = const_cast<char*>(cppStr.c_str());
      

      char* cStr = const_cast<char*>(cppStr.data());
      

      char* cStr = &cppStr[0];
      

      注意,只要您触摸它,cppStr 可能会被重新分配,从而使您的 cStr 无效。这会在某个时间点崩溃,尽管可能不会立即崩溃(更糟)。

      因此,无论如何,如果您要这样做。确保 cppStr.reserve(SOMETHING) ** 从中取出 cStr。这样,您至少可以稳定指针一段时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-26
        • 1970-01-01
        • 2013-08-26
        • 2022-01-05
        • 2020-07-09
        • 1970-01-01
        • 1970-01-01
        • 2012-03-03
        相关资源
        最近更新 更多