return c++ 中数组的简单方法

Simple way to return an array in c++

我正在尝试在 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::vectorstd::array (c++11)。所以我真的很感兴趣为什么我天真的解决方案实际上是 undefined behavior.

编辑:std::vector 将需要动态分配,在我的情况下应该避免(我需要操纵数千个 vr3)。我不能使用 std::array,因为我必须坚持使用 c++03。显然有人猜不到我​​的要求。

这个:

v3 & v = id( v );

还有这个:

int i = zero( i );

都是废话,因为你不能在它自己的初始化器中使用某些东西。有些编译器会就此警告您,但有些不会。

你可以做一个宏:

#define V3_UNIT {1,1,1}

现在您可以:

v3 v = V3_UNIT;

PTHREAD_MUTEX_INITIALIZER 是这种技术在野外的一个常见例子。

使用std::array:

#include <array>

using v3 = std::array<int, 3>;

v3 id()
{
  return {{ 1, 1, 1 }};
}

int main()
{
  v3 v = id();
}

您可以在大括号 {} 中初始化值。 喜欢:in = {1,1,1};

I am really interested why my naive solution is actually undefined behavior.

它是 UB 因为:您使用 id 的 return 值初始化引用 v,并且 id return 是它的引用范围。传递给 id 的参数是 v,因此您使用未初始化的自身初始化 v,而无需分配要引用的对象。

How can I use id with a single line of code ?

好吧,您可以简单地在一行中键入两个语句(并去掉多余的赋值):

v3 v; id(v);

但是,这样做会更简单:

v3 v{1, 1, 1};

I need to return an array.

如果你仔细阅读this page,你会发现你运气不好。数组不能被 returned 或作为参数传递。你可以做的是使用一个包装器 class 来保存数组。但是不需要自己实现,因为标准库已经提供了一个:std::array.

Of course I do not want to use std::vector or std::array

你已经把自己逼到了一个角落,因为你的需求相互矛盾。然后您需要自己重新实现 std::array 。我不建议你这样做。

您的问题是,在您的样本 main 中,在 v 情况下您没有 v3 anywhere。您只有 v3 的引用,没有任何内容可供他们引用。

你在 int 的情况下逃脱了它,因为你有一个真正的 int 可以参考。 (但这很可能是未定义的行为——它肯定非常狡猾。)

此代码是未定义的行为:

v3 & v = id( v );

在 clang 下你会得到警告:

warning: reference 'v' is not yet bound to a value when used within its own initialization [-Wuninitialized]


[编辑]

实际上我不是 100% 确定引用的自赋值是 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,但我想这只是因为很难找到标准的适当部分。