2

我在使用 clang 3.1(gcc 工作正常)时遇到了这个奇怪的问题(我在这里简化了代码)。是不当使用 std::function (按值传递)还是 clang 错误?

template <typename Container>
struct A
{
  using function_type = std::function<char(char)>;

  A(Container c, function_type f) : it_(c.begin()), f_(f) {}
  typename Container::value_type operator*() { return *it_; }

  typename Container::iterator it_;
  function_type f_;
};

template <typename Cont>
A<Cont> makeA(Cont c, std::function<char(char)> f)
{
  return A<Cont>(c, f);
}

char f(char ch) { return ch; }

int main()
{
  std::string s { "foo" };
  auto a = makeA(s, f); // wraps s.begin()
  std::clog << "main: " << *(s.begin()) << std::endl; // prints 'f'
  std::clog << "main: " << *a << std::endl; // prints garbage
  return 0;
}

我在 Max OS X Lion 上使用 Apple clang 4.1 (llvm 3.1)。

如果我将第二个参数的类型更改为其他类型(例如 int),则一切正常。

如果我直接从 ctor 构造 A 对象,而不是使用“make”工厂,那么一切正常。

我真的不明白这是一个clang bug还是我的误解。

4

1 回答 1

6

您将按string值传递给 的构造函数A,然后在本地字符串中创建一个迭代器。然后在构造函数的末尾销毁字符串,留下无效的迭代器和未定义的行为。

//`c` is a local copy of the string
A(Container c, function_type f) :
    //c.begin() returns an iterator into `c`
    it_(c.begin()),
    f_(f)
{
}//`c` is destroyed, leaving it_ as a dangling iterator

//Dereferences `it_` -- undefined behaviour
typename Container::value_type operator*() { return *it_; }
于 2012-12-30T12:01:10.993 回答