0

我试图保证我动态分配的内存没有指向任何地方。

我尝试了以下

template<typename T>
[...something here...]
T *mem = new T[size];

for ( int i=0; i<size; i++ )
{
    (mem+i) = NULL;
}  
[...something else there...]

就像一个人可以写

int *pInt = new int;
pInt = NULL;

但这不起作用,因为在上面的示例mem中不是“左值”?

为什么只有在我在堆上动态分配更多一种特定于类型的内存时才会出现这种情况?

另外如果我使用模板函数会发生一件奇怪的事情,因为它似乎是合法的

template<typename T>
[...something here...]
T mem = new T[size];

for ( int i=0; i<size; i++ )
{
    *(mem+i) = NULL;

    /* or the equivalent
    mem[i] = NULL;
    */
}  
[...something else there...]

怎么可能将NULL(基本上是int值 0)分配给基本上可以是任何东西的变量或对象?它可能是一个int变量,很好,它会起作用。但是如果我用std::string. 它根本不应该工作,对吧?那么为什么写这样的东西似乎是合法的呢?

是否可以自由编程泛型,但也有责任注意,而不是调用错误类型的泛型函数?

4

2 回答 2

1

但这不起作用,因为在上面的示例中“mem”不是“lvalue”?

实际上,您正在尝试重新分配临时指针mem+i;那没有意义。大概,您想将数组成员(mem[i]*(mem+i))设置为某些东西;尽管可能不会,NULL除非T应该是指针类型。

在单个对象的示例中,您将唯一的指针重新分配给分配的对象;因此您将无法使用或删除该对象。

怎么可能将 NULL (基本上是 int 值 0 )分配给基本上可以是任何东西的变量或对象?

因为,在 C++11 之前,唯一有效的空指针常量(因此NULL宏的唯一有效扩展)是零值整数常量;所以代码扩展为类似

*(mem+i) = 0;

这对许多类型都有效。如今,NULL可能(或可能不会)扩展为nullptr,在这种情况下,它仅对指针类型有效。

但是如果我用 std::string 调用模板函数呢?它根本不应该工作,对吧?

std::string有一个构造函数和赋值运算符,它带有一个指向 C 样式字符串的指针,例如

std::string hello = "Hello, world!";

这些也可以采用空指针,给出未定义的行为。

于 2014-03-06T19:18:24.530 回答
0

你的代码是:

for ( int i=0; i<size; i++ )
{
  (mem+i) = NULL;
}

在这种情况下(mem+i)是一个临时结果,称为右值。右值是临时的,你不能给它们赋值。您只能将值分配给左值。(顺便说一句,我认为这不是您想要做的:我猜您想更改指针显示的内存,而不是存储在指针中的地址值)

for ( int i=0; i<size; i++ )
{
  mem[i] = NULL;
 *(mem+i) = NULL;
}

在这种情况下,也会计算临时结果(在这两种情况下mem+i),但用于寻址正确的内存。因此,在这两种情况下,指向的内存都是左值。

如果您使用模板,则必须记住这些是模板;-) 如果模板没有在任何地方使用,则永远不会编译模板代码。如果使用它,则取决于您用作模板参数的变量/类的类型。

您可以编写以下代码:

template<typename T>
void func( T a)
{
  a.foo = "bar";
  a.my_func( 3.14);
}

这段代码看起来很奇怪,但它会为每个结构或类编译,该结构或类具有可以分配 aa的成员变量/对象和重载名称的成员函数或函数指针或对象。fooconst charoperator ()my_func

于 2014-03-06T19:36:56.733 回答