【问题标题】:Issue with returning a char* which is a struct返回作为结构的 char* 的问题
【发布时间】:2017-07-21 14:47:12
【问题描述】:

我是 C++ 新手,我正在尝试通过 char* 返回类中声明的结构。

#include<iostream>
using namespace std;
#include <cstring>

class test
{
public:
    struct pair
    {
        int a,b;
    };
    test(){
        pir=new pair;
        pir->a=1;
        pir->b=2;
    }

    void readx(char* str)
    {
        char* str2=new char[sizeof(pair)+1];
        str2=reinterpret_cast<char*>(pir);
        strncpy(str,str2,sizeof(pair));
    }
private:
    pair* pir;

};

int main()
{
    test t;
    char* ptr;
    t.readx(ptr);
    cout<<*((int*)ptr)<<endl;
    cout<<*((int*)ptr+4)<<endl;
    return 0;
}

我尝试了多种方法,但仍然未能返回可以重新解释为结构的 char*。实际上返回的 char* 只能保存第一个参数,丢失有关第二个参数的信息,尽管我使用了 strncpy 函数。此测试代码的输出是

1
0 

如何在类中返回关于 struct 的所有内容?

【问题讨论】:

  • strncpy() 用于复制以 NUL 结尾的字符串。尝试改用memcpy()
  • @MikeCAT 我刚试过memcpy(),但似乎也不起作用。
  • 结合了 memcpy 和 +1 的变化,真的很管用!非常感谢!!

标签: c++ struct char


【解决方案1】:
cout<<*((int*)ptr+4)<<endl;

这一行应该是:

cout<<*((int*)ptr+1)<<endl;

因为您已将ptr 转换为int *+1 表示将指针移动到下一个 4 个字节(int 的大小为 4)。

【讨论】:

  • 结合memcpy+1的变化,真的奏效了!非常感谢!!
【解决方案2】:

您的代码存在严重问题。如果它真的有效,那只是偶然的。

  1. 无论是strncpy 还是memset,您都使用它并不重要,因为您将未初始化的指针传递给写入它的函数:

    char* ptr;
    t.readx(ptr);
    

    ptr 指向哪里?它几乎可以指向任何地方,并且将其用作memcpy 目标是不可预测的。如果你不是很倒霉,你会遇到段错误/访问冲突。

  2. 您的 readx 方法做了一些疯狂的事情:

    char* str2 = new char[sizeof(pair)+1];
    str2 = reinterpret_cast<char*>(pir);
    

    在这里,您首先分配一些存储并将其地址分配给str2,然后将其重新分配给pir 的地址。你永远不能delete[]new[]分配的内存,所以你引入了内存泄漏。

  3. test 类的构造函数使用new 分配内存,但您没有相应的析构函数调用delete -> 内存泄漏。

然后你的ptr+4 问题已经被其他人指出了。在这里,您可以找到更正到您可以期望它执行您想要的操作的代码。

#include <iostream>
#include <cstring>

using namespace std;

class test
{
public:
    struct pair
    {
        int a, b;
    };

    test() : pir{ new pair() }
    {
        pir->a = 1;
        pir->b = 2;
    }

    ~test() { delete pir; }

    void readx(char* str)
    {
        memcpy(str, reinterpret_cast<char*>(pir), sizeof(pair));
    }
private:
    pair* pir;
};

int main()
{
    test t;
    char* ptr = new char[sizeof(test::pair)];
    t.readx(ptr);

    cout << *((int*)ptr) << endl;
    cout << *((int*)ptr + 1) << endl;

    delete[] ptr;

    return 0;
}

当您了解您的代码所读到的关于五法则的基本问题时。对于 test 类,您可以添加如下内容:

#include <algorithm>

class test
{
    //...

    test(test const& other) : pir{ new pair() }
    {
        pir->a = other.pir->a;
        pir->b = other.pir->b;
    }

    test& operator=(test const& other)
    {
        test copy(other);
        swap(*this, copy);
        return *this;
    }

    test(test&& other) noexcept : pir{ nullptr }
    {
        swap(*this, other);
    }

    test& operator=(test&& other) noexcept
    {
        swap(*this, other);
        return *this;
    }

    friend void swap(test& lhs, test& rhs)
    {
        std::swap(lhs.pir, rhs.pir);
    }
};

【讨论】:

  • 不要忘记规则 3(或自 C++11 起为 5)。
  • @O'Neil 添加了一些与五法则相关的代码。
  • 我无法期待更好的答案!真的感谢这些详细说明,而我对最后一部分的代码仍然很困惑。我马上检查五的规则。再次感谢您的帮助!
【解决方案3】:

您将 int 指针增加 4。这指向前面的 4 个整数。这不是你想要的。

cout<<*((int*)ptr+1)<<endl;

这应该会让你受益。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多