我正在尝试在C ++中使用以下id
函数。我原以为我可以这样做;
typedef int v3[3];
v3 & id( v3 & in )
{
in[0] = in[1] = in[2] = 1;
return in;
}
int main()
{
v3 & v = id( v );
return 0;
}
然而,这会导致g++
的段错误(我不清楚)。由于我可以使用标量类型执行以下操作:
int & zero( int & in )
{
in = 0;
return in;
}
int main()
{
int i = zero( i );
return 0;
}
如何将id
与一行代码一起使用?我想避免一个丑陋的解决方案,例如:
int main()
{
v3 v;
v3 & w = id( v );
}
当然我不想使用std::vector
或std::array
(c ++ 11)。所以我真的很感兴趣为什么我的天真解决方案实际上是undefined behavior
。
编辑:std::vector
将需要动态分配,在我的情况下应该避免(我需要操纵数以千计的vr3
)。我无法使用std::array
,因为我需要坚持c++03
。显然,人们无法猜测我的要求。
答案 0 :(得分:5)
此:
v3 & v = id( v );
而且:
int i = zero( i );
是胡说八道,因为你不能在自己的初始化程序中使用某些东西。有些编译器会对此发出警告,但有些则不会。
你可以制作一个宏:
#define V3_UNIT {1,1,1}
现在你可以做到:
v3 v = V3_UNIT;
PTHREAD_MUTEX_INITIALIZER
是这项技术的一个常见例子。
答案 1 :(得分:4)
使用std::array
:
#include <array>
using v3 = std::array<int, 3>;
v3 id()
{
return {{ 1, 1, 1 }};
}
int main()
{
v3 v = id();
}
答案 2 :(得分:4)
我真的很感兴趣为什么我天真的解决方案实际上是未定义的行为。
它的UB是因为:您使用v
的返回值初始化引用id
,并且id
返回作为其参数的引用。传递给id
的参数为v
,因此您可以使用未初始化的自我初始化v
,而无需分配要引用的对象。
如何在一行代码中使用id?
好吧,你可以简单地在一行上输入两个语句(并删除冗余的赋值):
v3 v; id(v);
但是,它会更简单:
v3 v{1, 1, 1};
我需要返回一个数组。
如果您仔细阅读this page,则会发现您运气不好。数组不能作为参数返回或传递。你可以做的是使用一个包含数组的包装类。但是没有必要自己实现它,因为标准库已经提供了一个:std::array
。
当然我不想使用std :: vector或std :: array
你已经把自己描绘成了一个有冲突欲望的角落。您需要自己重新实现std::array
。我不建议你这样做。
答案 3 :(得分:2)
您的问题是,在您的样本中main
,如果您没有v3
。您只能引用v3
,并且没有任何内容供他们参考。
你在int
案例中侥幸成功,因为你有真正的真实int
可以参考。 (但它可能是未定义的行为 - 它当然非常狡猾。)
答案 4 :(得分:1)
此代码是未定义的行为:
v3 & v = id( v );
在clang下你会收到警告:
警告:在自己的初始化中使用引用'v'尚未绑定到某个值[-Wuninitialized]
[编辑]
实际上我并不是百分之百确定如果自我指定引用是UB或格式错误的代码,我发现有关此主题的有趣讨论:
Why is GCC tricked into allowing undefined behavior simply by putting it in a loop? http://www.open-std.org/pipermail/ub/2014-September/000506.html
这表明它应该是相当不合理的 - 但看起来讨论正在进行中。关于此类代码的最常见评论是nonsense
,但我想这只是因为很难找到相应的标准部分。
答案 5 :(得分:0)
您可以在大括号{}中初始值。
喜欢:in = {1,1,1};