【问题标题】:How do I appropriately set the pointer to a new structure?如何适当地将指针设置为新结构?
【发布时间】:2013-09-10 10:50:03
【问题描述】:

我有一个关于在 c++ 中初始化新结构的问题。我是 C++ 新手。

typedef struct 
{
   int n;
   char anArray*;
}  myStruct;

void newStruct ( myStruct **ms, int x)
{
   myStruct* local_ms = new myStruct;
   local_ms->n = x;
   local_ms->anArray= new char[sizeof(char)*n];
   ms = &local_ms;
}

当我使用 void 指针调用 newStruct 时,我的意图是让它在 myStruct 中分配内存,然后将指向新结构的指针存储在 ms 中,以供以后使用。不幸的是,我认为 local_ms 仅在范围内是本地的,因此在从 newStruct 返回时会丢失。

话虽如此,我不确定如何正确初始化 myStruct!想法?

【问题讨论】:

  • 如果你是 C++ 新手,现在是read a book 的好时机,不要再像 C 一样写了。
  • 请避免在指针中传递东西的c风格(并避免一般的指针)
  • 我在这里看到的关于 C++ 语言的唯一内容是 new 而不是 malloc。遗憾的是我无法将问题的标签修改为C,因为这意味着我必须修改问题的代码。

标签: c++ object pointers struct


【解决方案1】:

“我认为 local_ms 仅在范围内是本地的,因此在返回时会丢失 来自新结构。”

变化:

ms = &local_ms;

到:

*ms = local_ms;

将有助于避免将newStruct 对象的指针分配给*ms 的问题。

【讨论】:

    【解决方案2】:
    ms = &local_ms;
    

    这会修改 local 指针 ms 以指向另一个 local 指向已分配结构的指针。但是,您想要的是修改调用者的指针。 ms 是指向那个的指针,所以你想修改ms 指向的东西:

    *ms = local_ms;
    

    但这不是 C,因此您可以使用更简单的引用语义:

    void newStruct ( myStruct *& ms, int x)
    //                        ^^ reference to pointer
    {
        // ...
        ms = local_ms;
    }
    
    // usage
    myStruct * ms;
    newStruct(ms, 42);
    

    但是语言(C 或 C++)提供了一种更简洁的方法来从函数返回值:您可以从函数返回值。

    myStruct * newStruct(int x)
    {
        // ...
        return local_ms;
    }
    
    // usage
    myStruct * ms = newStruct(42);
    

    但在 C++ 中,我们可以使用 构造函数,而不是任意函数来初始化新对象:

    struct myStruct {              // no need for that typedef nonsense
        explicit myStruct(int n) : 
            n(n), 
            anArray(new char[n])   // sizeof(char) is 1 by definition
        {}
    
        int n;
        char *anArray;             // * goes before the variable name
    };
    
    // usage
    myStruct ms(42);               // don't use `new` unless you really need it
    

    现在只缺少一件事:anArray 永远不会被删除,导致内存泄漏。最简单的解决方法是使用标准库中的 动态数组 类型:stringvector

    struct myStruct {
        explicit myStruct(int n) : n(n), anArray(n) {}
    
        int n;
        std::string anArray;
    };
    

    当然,n 现在是多余的;您应该摆脱它并改用anArray.size()。这意味着结构本身毫无意义。你只需要

    std::string ms(42);
    

    【讨论】:

    • 谢谢。这似乎奏效了。如果 anArray 比简单的字符数组(字符串)更复杂怎么办。比如说,指向另一个对象的指针?那么你将如何纠正内存泄漏呢?
    【解决方案3】:
    #include <memory>
    #include <iostream>
    
    // [A] Starting with:
    
    typedef struct
    {
       int n;
       // Not char anArray*;
       char* anArray;
    }  myStruct;
    
    void newStruct ( myStruct **ms, int x)
    {
       myStruct* local_ms = new myStruct;
       local_ms->n = x;
       // Fix: use x
       local_ms->anArray = new char[sizeof(char)*x];
       ms = &local_ms;
    }
    
    //  [B] Avoid myStruct **ms, use std::size_t
    //      and get rid of sizeof(char) (which is one, always)
    
    myStruct* newStruct (std::size_t x)
    {
       myStruct* ms = new myStruct;
       ms->n = x;
       ms->anArray= new char[x];
       return ms;
    }
    
    // [C] Manage memory in a class (pair new/delete).
    //     Btw. typedef struct is C (not C++)
    
    class myStruct2
    {
        public:
        myStruct2(std::size_t n)
        :   n(n), anArray(new char[n])
        {}
    
        ~myStruct2() {
            delete [] anArray;
        }
    
        std::size_t size() const { return n; }
        const char* array() const { return anArray; }
        char* array() { return anArray; }
    
    
        private:
        // If you do not define these, avoid copies (C++11 has '= delete'):
        myStruct2(const myStruct2&);
        myStruct2& operator = (const myStruct2&);
    
        std::size_t n;
        char* anArray;
    };
    
    // Still having a new without delete in the same (logically) scope - which is bad:
    myStruct2* newStruct2 (std::size_t n)
    {
       return new myStruct2(n);
    }
    
    // [D] Manage memory with a shared pointer.
    
    // Still having an new without a delete in the same (logically) scope,
    // but now the memory is managed by the shared pointer - that is good!
    // (If there is no std::shared_ptr: boost::shared_ptr)
    std::shared_ptr<myStruct2> make_shared_struct2(std::size_t n)
    {
       return std::shared_ptr<myStruct2>(new myStruct2(n));
    }
    
    // [E] Avoid the pointer to myStruct2
    // If you have defined the copy constructor and assignment operator:
    // myStruct2 make_struct2(std::size_t n)
    // {
    //    return myStruct2(n);
    // }
    
    // [F] But actually it is trivial
    typedef std::vector<char> myStruct3;
    
    myStruct3 make_struct3(std::size_t n)
    {
        return myStruct3(n);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 2017-10-06
      • 2012-08-05
      • 1970-01-01
      • 2011-01-20
      相关资源
      最近更新 更多