0

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

4

3 回答 3

1

“我认为 local_ms 仅在范围内是本地的,因此在从 newStruct 返回时会丢失。”

改变:

ms = &local_ms;

至:

*ms = local_ms;

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

于 2013-09-10T10:59:31.587 回答
0
ms = &local_ms;

这会修改本地指针ms以指向另一个指向已分配结构的本地指针。但是,您想要的是修改调用者的指针。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永远不会被删除,导致内存泄漏。最简单的解决方法是使用标准库中的动态数组类型:要么string要么vector.

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

    int n;
    std::string anArray;
};

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

std::string ms(42);
于 2013-09-10T12:55:26.210 回答
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);
}
于 2013-09-10T12:56:22.950 回答