You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用decltype实例化std::vector?编译报错原因解析

问题分析:使用decltype(*iter)实例化std::vector失败的原因

问题描述

尝试使用decltype(*iter)实例化std::vector vD2时编译失败,报错信息为“forming pointer to reference type ‘func()::data&’”,存在两个疑惑:

  • 为什么*iter的类型不是data?
  • 该编译错误的具体含义是什么?

测试代码

#include<vector>
#include<iostream>
#include<type_traits>

using std::vector;
using std::is_same_v;
using std::cout;
using std::endl;

int func() 
{
  struct data
  {
    int i;
    char c;
  };

  vector<data> vD1;

  vD1.push_back(data());
  vD1.at(0).i = 0;
  vD1.at(0).c = 'a';

  auto iter = vD1.begin();
  vector<decltype(*iter)>vD2;

  if(is_same_v<decltype(vD1),decltype(vD2)>)
  {
    cout << "similar types" << endl;
  }
  else
  {
    cout << "dissimilar types" << endl;
  }
  
    return 0;   
}

int main() 
{
    auto exit = (int (*)()) &func;
    
    std::cout << exit() << std::endl;
}

编译报错信息

g++ -c -o code.o code.cpp -ggdb -g3 -pedantic-errors -Wall -Wextra -Wfatal-errors -Wpedantic -std=c++20
In file included from /usr/include/c++/11/x86_64-redhat-linux/bits/c++allocator.h:33,
                 from /usr/include/c++/11/bits/allocator.h:46,
                 from /usr/include/c++/11/vector:64,
                 from code.cpp:1:
/usr/include/c++/11/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<func()::data&>’:
/usr/include/c++/11/bits/allocator.h:124:11:   required from ‘class std::allocator<func()::data&>’
/usr/include/c++/11/bits/stl_vector.h:87:21:   required from ‘struct std::_Vector_base<func()::data&, std::allocator<func()::data&> >’
/usr/include/c++/11/bits/stl_vector.h:389:11:   required from ‘class std::vector<func()::data&>’
code.cpp:25:26:   required from here
/usr/include/c++/11/ext/new_allocator.h:103:7: error: forming pointer to reference type ‘func()::data&’
  103 |       allocate(size_type __n, const void* = static_cast<const void*>(0))
      |       ^~~~~~~~
compilation terminated due to -Wfatal-errors.

问题解答

  1. 为什么decltype(*iter)是data&而非data?
    std::vector的迭代器解引用(operator*)返回的是容器元素的左值引用——你可以通过*iter修改容器内的元素,证明这是左值。而decltype的推导规则是:如果表达式是左值,推导结果会保留引用属性,因此decltype(*iter)得到的类型是data&,而非原始的data类型。

  2. 编译错误的含义是什么?
    std::vector的模板参数要求是可分配内存的对象类型,但引用不是独立对象,只是另一个对象的别名,无法单独占用内存。当实例化vector<data&>时,vector底层的分配器会尝试创建指向data&的指针(即data&*),但C++语法明确禁止“指向引用的指针”这种类型,因此编译器抛出该错误。

解决方法

要通过迭代器推导得到元素的原始类型,需要用std::remove_reference_t去除引用属性:

vector<std::remove_reference_t<decltype(*iter)>> vD2;

或者更直接地使用容器的value_type:

vector<decltype(vD1)::value_type> vD2;

修改后,vD2的类型会和vD1一致,编译即可通过。

内容的提问来源于stack exchange,提问作者Vinod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 17:37:03