簡體   English   中英

Apple LLVM 7.0.0的c ++ 11參數包錯誤行為,但適用於GCC-5.1

[英]c++11 parameter pack wrong behaviour with Apple LLVM 7.0.0 but works with GCC-5.1

由於該問題的先前版本,感謝@Gene,我現在可以使用一個更簡單的示例重現此行為。

#include <iostream>
#include <vector>

class Wrapper
{
  std::vector<int> const& bc;
public:
  Wrapper(std::vector<int> const& bc) : bc(bc) { }
  int GetSize() const { return bc.size(); }
};

class Adapter
{
  Wrapper wrapper;
public:
  Adapter(Wrapper&& w) : wrapper(w) { }
  int GetSize() const { return wrapper.GetSize(); }
};

template <class T>
class Mixin : public Adapter
{
public:
  //< Replace "Types ... args" with "Types& ... args" and it works even with Apple LLVM
  template <class ... Types>
  Mixin(Types ... args) : Adapter(T(args...)) { }
};

int main()
{
  std::vector<int> data;
  data.push_back(5);
  data.push_back(42);
  Mixin<std::vector<int>> mixin(data);
  std::cout << "data:  " << data.size() << "\n";
  std::cout << "mixin: " << mixin.GetSize() << "\n";
  return 0;
}

使用Apple LLVM的結果,並通過-std=c++11-std=c++14

data:  2
mixin: -597183193

有趣的是,我還在@ideone上測試了此代碼,該代碼使用了啟用了C ++ 14的gcc-5.1,並且可以按預期工作!

data:  2
mixin: 2

為什么mixin.GetSize()在Clang上返回垃圾值,為什么它在GCC-5.1中起作用?

@Gene建議我使用Types ... args來創建向量的臨時副本(使用Types& ... args使其可以與LLVM一起使用),但是該副本將包含相同的元素(因此也具有相同的元素)尺寸)。

您有一個懸空的引用,並且mixin.GetSize()產生未定義的行為

  • Mixin的構造函數內部, T = std::vector<int> ,因此Adapter(T(args...))Adapter的構造函數傳遞給臨時的std::vector<int>
  • Adapter的構造函數參數是Wrapper&& ,但我們將其傳遞給std::vector<int>&& ,因此我們調用Wrapper的隱式轉換構造函數
  • Wrapper的構造函數參數是std::vector<int> const& ,我們將其傳遞給std::vector<int>&& 允許將rvalue綁定到const-lvalue引用,因此在語法上可以很好地進行編譯,但是實際上,我們將Wrapper::bc綁定到了一個臨時對象
  • 一旦構造完成,在Mixin的構造函數中創建的臨時項的生存期結束,並且Wrapper::bc成為懸空引用; 調用Adapter::GetSize現在產生UB

Mixin的構造函數參數從Types...更改為Types&...Adapter(T(args...)) 仍將 Adapter的構造函數傳遞給臨時std::vector<int> ; 它之所以似乎起作用,是因為您看到的是UB的不同表現形式(可能是由於減少了std::vector<int>的副本,所以堆棧看起來有些不同)。 即, 兩個版本的代碼都同樣損壞/錯誤!

因此,要具體回答:

為什么mixin.GetSize()在Clang上返回垃圾值,為什么它在GCC-5.1中起作用?

因為未定義的行為是未定義的行為。 ;-]出現工作是一種可能的結果,但是代碼仍然被破壞,正確的表象純粹是膚淺的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM