First of all, I want to reassure you all that I am asking this question out of curiosity. I mean, don't tell me that if I need this then my design has problems because I don't need this in real code. Hope I convinced you :) Now to the question:
首先,我想向你们保证,我问这个问题是出于好奇。我的意思是,不要告诉我,如果我需要这个,那么我的设计就有问题了,因为我在真正的代码中不需要这个。希望我说服你:)现在的问题:
For most types T we can write
对于大多数类型T,我们可以写
T* p = new T;
now what if T is an array type?
如果T是数组类型呢?
int (*p)[3] = new ???; //pointer to array of 3 = new ???
I tried this:
我试着这样的:
typedef int arr[3];
arr* p = new arr;
but this doesn't work.
但这是行不通的。
Is there any valid syntax for this or it is impossible in C++. If it is impossible, then why? Thanks
是否有任何有效的语法,或者在c++中是不可能的。如果不可能,那为什么呢?谢谢
Edit: i am guessing I wasn't clear enough. I want to be able to use it in this situation:
编辑:我猜我还不够清楚。我想在这种情况下使用它:
void f(int(&)[3]);
int (*p)[3] = new ???;
f(*p);
4 个解决方案
#1
10
The reason you can't do it is that new int[3]
already allocates exactly what you want, an object of type int[3]
. It's just that what the new-expression returns, is a pointer to its first element. 5.3.4/1:
不能这样做的原因是新的int[3]已经分配了您想要的对象,类型为int[3]的对象。新表达式返回的是指向第一个元素的指针。5.3.4/1:
If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.
如果实体是一个非数组对象,则新表达式返回一个指向所创建对象的指针。如果是数组,则新表达式返回指向数组初始元素的指针。
Returning a pointer to the first element is what allows the 3
to be unknown until runtime, so I suppose that by knowing it in advance, you've tripped over flexibility that you aren't using.
返回一个指向第一个元素的指针是允许3在运行时之前未知的,所以我假设通过提前知道它,您已经在不使用的灵活性上犯了错误。
I guess the ways around this are to reinterpret_cast back to the pointer type you want (not necessarily portable), or to allocate a struct containing an int[3]
(and use a pointer to its data member).
我想解决这个问题的方法是重新解释t_cast回您想要的指针类型(不一定是可移植的),或者分配一个包含int[3]的结构体(并使用指向其数据成员的指针)。
[Edit: er, yeah, or FredOverflow's idea, which has neither disadvantage, but requires use of delete[]
instead of delete
.]
[编辑:嗯,是的,或者FredOverflow的想法,它没有缺点,但是需要使用delete[]而不是delete。]
I guess the moral is, if you write templates that naively allocate some unknown type T
with new
, then the template won't work when someone passes an array type as T
. You'll be assigning it to the wrong pointer type, and if you fix that (perhaps with auto
), you'll be deleting it wrongly.
我想,如果你写模板,天真地分配一些未知类型T和新的,那么模板不会工作当有人通过一个数组类型为T .你会将它分配给错误的指针类型,如果你修复与汽车(可能),你会错误地删除它。
Edit in answer to j_kubik's question:
编辑回答j_kubik的问题:
Here's one way to distinguish between array and non-array types. If you write a function like this, that returns an object that holds the pointer and is capable of correctly deleting it, then you have a generic new/delete for any type T.
这里有一种区分数组和非数组类型的方法。如果您编写这样的函数,它返回一个对象,该对象保存指针并能够正确地删除它,那么对于任何类型的T,您都有一个通用的new/delete。
#include <iostream>
template <typename T>
void make_thing_helper(T *) {
std::cout << "plain version\n";
}
template <typename T, int N>
void make_thing_helper(T (*)[N]) {
std::cout << "array version\n";
}
template <typename T>
void make_thing() {
make_thing_helper((T*)0);
}
int main() {
typedef int T1;
typedef int T2[3];
make_thing<T1>();
make_thing<T2>();
}
#2
11
To get a pointer to an array from new
, you have to dynamically allocate a two-dimensional array:
要从new获取指向数组的指针,必须动态分配一个二维数组:
int (*p)[3] = new int[1][3];
#3
2
You could always use boost::array, which will be in C++0x. Otherwise, any solution will be awkward at best: arrays are broken in C, and C++ maintains compatilibity with C in this respect. Fred Overflow offered one solution; even easier (but syntactically noisy) would be to wrap the array in a struct: struct A { int arr[3]; }; and allocate and manipulate this.
您可以使用boost:::array,它将在c++ 0x中。否则,任何解决方案都将是笨拙的:数组在C中被破坏,在这方面c++与C保持了兼容性。Fred Overflow提供了一个解决方案;更简单的(但语法上有干扰)是将数组包装成一个struct: struct a {int arr[3];};分配和操作这个。
#4
-2
You just do
你就做
int *p = new unsigned int [3]
You can then use *p
as a pointer or an array i.e. *(p+1) or p[1]
然后可以使用*p作为指针或数组,例如*(p+1)或p[1]
#1
10
The reason you can't do it is that new int[3]
already allocates exactly what you want, an object of type int[3]
. It's just that what the new-expression returns, is a pointer to its first element. 5.3.4/1:
不能这样做的原因是新的int[3]已经分配了您想要的对象,类型为int[3]的对象。新表达式返回的是指向第一个元素的指针。5.3.4/1:
If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.
如果实体是一个非数组对象,则新表达式返回一个指向所创建对象的指针。如果是数组,则新表达式返回指向数组初始元素的指针。
Returning a pointer to the first element is what allows the 3
to be unknown until runtime, so I suppose that by knowing it in advance, you've tripped over flexibility that you aren't using.
返回一个指向第一个元素的指针是允许3在运行时之前未知的,所以我假设通过提前知道它,您已经在不使用的灵活性上犯了错误。
I guess the ways around this are to reinterpret_cast back to the pointer type you want (not necessarily portable), or to allocate a struct containing an int[3]
(and use a pointer to its data member).
我想解决这个问题的方法是重新解释t_cast回您想要的指针类型(不一定是可移植的),或者分配一个包含int[3]的结构体(并使用指向其数据成员的指针)。
[Edit: er, yeah, or FredOverflow's idea, which has neither disadvantage, but requires use of delete[]
instead of delete
.]
[编辑:嗯,是的,或者FredOverflow的想法,它没有缺点,但是需要使用delete[]而不是delete。]
I guess the moral is, if you write templates that naively allocate some unknown type T
with new
, then the template won't work when someone passes an array type as T
. You'll be assigning it to the wrong pointer type, and if you fix that (perhaps with auto
), you'll be deleting it wrongly.
我想,如果你写模板,天真地分配一些未知类型T和新的,那么模板不会工作当有人通过一个数组类型为T .你会将它分配给错误的指针类型,如果你修复与汽车(可能),你会错误地删除它。
Edit in answer to j_kubik's question:
编辑回答j_kubik的问题:
Here's one way to distinguish between array and non-array types. If you write a function like this, that returns an object that holds the pointer and is capable of correctly deleting it, then you have a generic new/delete for any type T.
这里有一种区分数组和非数组类型的方法。如果您编写这样的函数,它返回一个对象,该对象保存指针并能够正确地删除它,那么对于任何类型的T,您都有一个通用的new/delete。
#include <iostream>
template <typename T>
void make_thing_helper(T *) {
std::cout << "plain version\n";
}
template <typename T, int N>
void make_thing_helper(T (*)[N]) {
std::cout << "array version\n";
}
template <typename T>
void make_thing() {
make_thing_helper((T*)0);
}
int main() {
typedef int T1;
typedef int T2[3];
make_thing<T1>();
make_thing<T2>();
}
#2
11
To get a pointer to an array from new
, you have to dynamically allocate a two-dimensional array:
要从new获取指向数组的指针,必须动态分配一个二维数组:
int (*p)[3] = new int[1][3];
#3
2
You could always use boost::array, which will be in C++0x. Otherwise, any solution will be awkward at best: arrays are broken in C, and C++ maintains compatilibity with C in this respect. Fred Overflow offered one solution; even easier (but syntactically noisy) would be to wrap the array in a struct: struct A { int arr[3]; }; and allocate and manipulate this.
您可以使用boost:::array,它将在c++ 0x中。否则,任何解决方案都将是笨拙的:数组在C中被破坏,在这方面c++与C保持了兼容性。Fred Overflow提供了一个解决方案;更简单的(但语法上有干扰)是将数组包装成一个struct: struct a {int arr[3];};分配和操作这个。
#4
-2
You just do
你就做
int *p = new unsigned int [3]
You can then use *p
as a pointer or an array i.e. *(p+1) or p[1]
然后可以使用*p作为指针或数组,例如*(p+1)或p[1]