在你读之前: const_reference
是typedef,不需要 const T&
正如你所看到的那样 std::vector<bool>::const_reference = bool
。请在阅读其他内容时牢记这一点,以便正确理解(正如值得一提的,这对很多人来说很难)。
我想将STL容器用于简单类型(例如 int
)并发现他们使用次优 const T&
“反模式” - 它适用于大类,但在没有内联时对于简单/基本类型是次优的 - 考虑嵌入式系统,例如在ARM / ATSAM4L上,实例化。
问题是:为什么例如 vector::push_back
重新设计的论点 (const value_type&)
代替 (Allocator::const_reference
)自C ++ 11以来?
通用应该是相同的 allocator
,但以另一种方式这样做将有助于我为定义的基本类型编写自定义分配器(或模板特化) const_reference
作为类型本身(见 vector<bool>::const_reference = bool
)。
问题2: 有没有 适配器 能为我做那件事的班级?
像这样的东西:
template<class T, class base = std::vector<T> >
class myvect: protected base {
public:
typedef T const_reference;
void push_back(const_reference value) {
base::push_back(value); }}
最终用法将是这样的:
typedef void (*action_t)(void*,int);
extern "C" void work(void *, action_t);
work(&vect, (action_t)&vect::push_back);
(注意: 忽略以前代码块中可能的转换问题,我希望你有这个想法。)
编辑: vector::const_reference
直接定义为 const value_type&
但在我看来应该被定义为 Alloc::const_reference
然后可以很容易地改变(vector<int, MyAllocator<int> >
)。 (这在C ++ 11中有所改变,它被定义为Alloc :: const_reference但现在是const value_type&)
编辑: func(const T&)
有时被描述为 “反模式” 这里是stackoverflow,因为它对于没有内联的基本类型来说是次优的(是的,编译器生成最佳代码,即使对于 func(const int&)
如果内联,但就是这样 如果。 func(int)
会做得更好)
结论: 问题似乎在于行为 const
因此 const T&
。 const
并不是真的意思 不得改变 但 不要换 因此 const T&
需要(并明确定义和使用) 作为返回类型 对于很多方法。创建 自定义适配器类 似乎是优化的最佳方式,它似乎被广泛接受 std::vector<bool>
是奇怪的例外,应该在单独的类中(例如 dynamic_bitset
)。
它的评论有点长,所以我会用“答案”来谈论它,但实际上这不是答案。
你想要的功能,改写:
您希望te能够避免某些方法中的“通过const引用”惯用法,以避免小型类型的指针操作所产生的“减速”,而不是直接复制。对于push_back尤其如此,如果push_back有一个具有可配置类型的参数(通过模板意味着在容器类型中,比如allocator模板参数),那么它可以让你感觉良好。
例如,通过使用与allocator模板参数相同的方法,可以提供所需的功能,可以使用typename指定“push back”参数中使用的类型。
但它不是那样设计的,因为它似乎是一种复杂性,根本不值得。
由于编译器优化会消除基本类型的大量开销,因此不值得,因为静态分析更容易在基本类型上运行。
其次,通过引用传递int与在方法参数中复制它的“丢失时间”被认为是平台特异性,无法在“虚拟机”级别(语言编写者必须自己放置的级别)进行验证)。更不用说这里的“过早优化”会导致坦率的代码膨胀获得,作为一般目的的合理权衡,它被彻底驱逐。这也是因为在设计时,您会想到基本类型,如稀有性和可能包含的可能类型的无穷大。
PS:
最后,使用typedef作为分配器的一部分似乎是一个非常糟糕的责任分离,拥有自己的模板参数似乎更清晰,因为它与分配无关,而是与实现选择的特定方法有关。容器。
PS2 /编辑:
我想补充一下,正如评论中所说的那样 vector<bool>::const_reference
不能作为可能做的例子,因为这是标准中的错误,实际上是对STL的侵犯 需求 容器定义的 ..::reference
如 T&
。问题的进一步证明是 vector<bool>::reference
(不是const)不是bool,它是一个未指定的类(_Bit_reference
在gcc中,它作为一个代码,用于访问和变换一个位,包含在向量中,它将作为“虚拟”bool值的存储支持,使其看起来像现有的一样。这些奇怪的东西不能移植到通用向量,因为它们不符合宽STL要求。但它并没有使正交方法失效,就像我提到的那样 pass_for_copy_param_type
这可能是一个可参数化的新typedef,并且在今天编写“const value_type&”的某些地方(合适的地方)用于替换。但这正是我之前提到过的代码膨胀。我确信这么少的人肯定不值这么多。
改变意义 const_reference
会破坏返回a的方法的语义 const
参考:
std::vector<int> my_vector(100);
// this needs an lvalue ref
my_vector[42]++;
// I want to track this value
std::vector<int>::const_reference i = my_vector[3];
// I expect i to be be 1 after this
my_vector[3]++;
允许更改const_reference的类型会破坏与std :: vector和容器要求的兼容性。该标准明确假定const_reference是一个引用并使用它多次,例如data()和front()的语义。在23.3.6.4中,它表示“对于非空向量,data()==&front()”。这使得您的修改无效,因为修改后,front()将不再返回对已分配内存的引用,因此地址会有所不同。实际上,它将是临时对象的地址。
我还认为大多数编译器都会优化使用const&away的任何额外成本。
std :: vector <bool>是一个不好的例子,因为它不是STL意义上的容器模型。大多数人都同意它不应该在标准中定义,例如 https://isocpp.org/blog/2012/11/on-vectorbool。