我试图保证动态分配的内存无法指向。
我尝试了以下
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
调用模板函数,该怎么办?它应该不起作用,对吗?那么为什么写这样的东西似乎是合法的呢?
是否可以自由编程泛型,但也有责任注意,而不是调用错误类型的某些通用函数?
答案 0 :(得分:1)
但它不起作用,因为在上面的例子中“mem”不是“左值”?
的确,您正在尝试重新分配临时指针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!";
这些也可以采用空指针,给出未定义的行为。
答案 1 :(得分:0)
您的代码是:
for ( int i=0; i<size; i++ )
{
(mem+i) = NULL;
}
在这种情况下,(mem+i)
是临时结果,称为rvalue。 rvalues是临时的,你不能为它们赋值。您只能为左值分配值。 (顺便说一下,我认为这不是你想做的事情:我想你想改变指针显示的内存而不是指针中存储的地址值)
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);
}
此代码看起来是strang,但它将为每个a
编译,该foo
具有成员变量/对象const char
的任何结构或类,可以为其分配operator ()
和成员函数或函数指针或具有名称my_func
的重载{{1}}的对象。