根据Herb Sutter的文章http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/,以下代码是正确的:
#include <iostream>
#include <vector>
using namespace std;
vector<vector<int>> f() { return {{1},{2},{3},{4},{5}}; }
int main()
{
const auto& v = f();
cout << v[3][0] << endl;
}
Run Code Online (Sandbox Code Playgroud)
即生命周期v延长到vconst参考的生命周期.事实上,根据valgrind的说法,这可以很好地用gcc和clang编译而且没有泄漏.
但是,当我main这样改变功能时:
int main()
{
const auto& v = f()[3];
cout << v[0] << endl;
}
Run Code Online (Sandbox Code Playgroud)
它仍然编译,但valgrind警告我函数的第二行中的无效读取,因为第一行中的内存是空闲的.
这是符合标准的行为还是g ++(4.7.2)和clang(3.5.0-1~exp1)中的错误?
如果它符合标准,对我来说似乎很奇怪......哦.
我正在使用GADT为货币创建基本维度(如物理维度)系统.尺寸(例如美元,美元/欧元,欧元/美元)表示为幻像类型.我希望能够以例如"10.3USD"或"0EUR"的方式打印一定数量的货币,并使用Show打印例如"10.3USD/EUR"的费率.我不太确定如何解释我的问题,所以我将举例说明我是如何解决它的:
{-# LANGUAGE GADTs #-}
class (Show a) => Currency a where unphantom :: a
data USD = USD deriving Show
data EUR = EUR deriving Show
instance Currency USD where unphantom = USD
instance Currency EUR where unphantom = EUR
data Amount a where
Amount :: Currency a => Float -> Amount a
instance Show (Amount a) where
show (Amount x) = show x ++ show (unphantom :: a)
data Rate a b where
Rate :: (Currency a, Currency …Run Code Online (Sandbox Code Playgroud) 这是我认为可能有用但我没有看到在gcc的标准库中实现的东西.
基本上,在我看来,STL实现可以添加断言来检测(在运行时)简单的错误,如越界访问.我猜这些访问在标准中无论如何都是未定义的行为,所以肯定会打印错误消息并且-optionally-aborting将符合标准.
这些断言当然可以在编译时通过旧的NDEBUG标志或其他标志来关闭.
作为一个小例子,我希望此代码中止:
#include <vector>
int main()
{
return std::vector<int>{1,2}[2];
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我充分意识到像valgrind这样的工具的存在,但这可能是一个奖励.此外,像valgrind这样的内存检查工具不能保证在向量缩小后检测某些错误,例如访问越界元素,因为实现可能不会立即重新分配底层内存.