这是一个使用函数的(人工)示例,该函数返回一个匿名结构并执行“有用”:
#include <iostream>
template<typename T>
T* func(T* t, float a, float b) {
if(!t) {
t = new T;
t->a = a;
t->b = b;
} else {
t->a += a;
t->b += b;
}
return t;
}
struct {
float a, b;
}* foo(float a, float b) {
if(a==0) return 0;
return func(foo(a-1,b), a, b);
}
int main() {
std::cout << foo(5,6)->a << std::endl;
std::cout << foo(5,6)->b << std::endl;
void* v = (void*)(foo(5,6));
//[1] delete f now because I know struct is floats only.
float* f = (float*)(v);
std::cout << f[0] << std::endl;
std::cout << f[1] << std::endl;
delete[] f;
return 0;
}
我想讨论几点:
func
中创建一个对象的实例,我可以在不返回指针的情况下做类似的事情吗?顺便说一下,函数foo(a,b)
的作用是返回一个包含两个数字的结构,即从1到a的所有数字的总和以及a和b的乘积。
也许行new T
可以使用boost :: shared_ptr以某种方式避免泄漏,但我没有尝试过。那会有用吗?
我想我只是试图将匿名结构删除为浮点数组,类似于float * f = new float [2]。哪个可能是错的,正如下面的评论所示,那么可以做些什么呢?我可以删除吗?
我可以在VS2008上“按原样”编译和运行此代码,VS可能正在使用某些非标准扩展,但它确实运行并给出15和30作为答案。
从答案中我相信这个装置是VS2008特定的实体,它不符合标准,因此不便携。太糟糕了,我本来希望看到Stackoverflow或Boost人们想出的伏都教,如果这是他们的武器库:)。谢谢大家。
答案 0 :(得分:9)
目前,您的代码不可移植;例如,它不会与gcc
构建。
标准的第14.3.1 / 2节说:
本地类型,没有的类型 链接,未命名类型或类型
从任何这些类型复合而成 不得用作模板 -
参数用于模板 型参数。
有关可能的演变,请参阅C++ Standard Core Language Defect Reports, Revision 69和Paper N2657中的第488项。
假设您的代码格式正确,那么:
您可以重写:
std::cout << foo(5,6)->a << std::endl;
作为
std::cout << std::auto_ptr(foo(5,6))->a << std::endl;
如果匿名结构具有另一种类型的构造函数(匿名或不是匿名,您可以在方法体内初始化),则可以返回匿名struct
按值 - 当然,除了如何为匿名结构指定构造函数之外? :)
除了一种极其错综复杂的尝试不为结构指定明确名称的方式之外,我看不到真实世界的使用;一个人通常会使用匿名结构(在C ++中不是技术上合法的,但是由各种编译器支持作为扩展)以便不污染命名空间,通常是通过立即实例化(例如,您可以看到一次性仿函数被实例化并传递下来作为匿名结构 - 再次,技术上不合法的C ++。)
感谢gf
指向C ++标准相关部分的链接,该部分涉及可能未在返回类型中定义的新类型。
从评论中提到这一点:在分配了delete[]
(而不是new
)的内存上调用new[]
是对堆损坏的邀请。在一个你不知道的类型的指针上调用delete
在技术上是未定义的(应该调用哪个析构函数?)但是在POD(你的匿名结构是一个)的情况下你可以在这个中逃脱它可怕的 hackish方式:
delete (int*)f;
当然,如果您的代码神奇地构造良好,std::auto_ptr
本来可以保留匿名类型,并且会正确而优雅地为您调用delete
。
答案 1 :(得分:5)
您在标准C ++中无法做到 - 根据§8.3.5/ 6 (函数声明符,C ++ 03),返回类型中不允许使用类型定义:
不应在返回或参数类型中定义类型。
在这种情况下,Visual Studio不兼容。
答案 2 :(得分:3)
C ++ Standard不允许使用匿名结构。
答案 3 :(得分:1)
我想不出任何合理的用法。除了内存泄漏,这是实现您想要的目标的一种非常难以理解的方式。它使您的读者能够充分考虑代码的作用。而且还不知道谁应该删除main()中的'f'。它应该用delete []删除还是删除?
我会在构造函数中使用一个带'a'和'b'的类。它将有两种方法来获取两个计算的struct成员。在课堂内将有私人mehotds,使用普通循环来计算你想要的东西。然后您的API将如下所示:
void main()
{
MyCalculator myCalc(5, 6);
double sumOfAllNumbers = myCalc.getSumOfAllNumbers();
double product = myCalc.getProduct();
}
答案 4 :(得分:1)
匿名结构的近似是一个元组。 Boost::Tuple现在可以在任何地方使用,TR1中有另一个[我假设与VS2008一起发布],其界面几乎相同。
#include <boost/tuple/tuple.hpp>
template<typename T>
boost::tuple<T, T>* func(boost::tuple<T, T>* t, float a, float b ) {
if(!t) {
t = new boost::tuple<T, T>(a, b);
} else {
boost::get<0>(*t) += a;
boost::get<1>(*t) += b;
}
return t;
}
boost::tuple<float, float>* foo(float a, float b) {
if(a==0) return 0;
return func(foo(a-1,b), a, b);
}
正如其他人所说,整体方案非常脆弱,但我想专注于元组而不是设计。