如何将指针适当地设置为新结构?

时间:2013-09-10 10:50:03

标签: c++ object pointers struct

我有一个关于在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!想法?

3 个答案:

答案 0 :(得分:1)

  

“我认为local_ms只在本地范围内,因此在返回时会丢失   来自newStruct。“

变化:

ms = &local_ms;

为:

*ms = local_ms;

有助于避免问题,该问题会将newStruct对象的指针指定给*ms

答案 1 :(得分:0)

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);

答案 2 :(得分:0)

#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);
}