小编vso*_*tco的帖子

通过从本地C风格的数组返回指针来获取悬空指针

我对以下代码感到有点困惑:

#include <iostream>

const char* f()
{
    const char* arr[]={"test"};
    return arr[0];
}

int main()
{
    auto x = f();
    std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,这段代码应该是UB(未定义的行为).我们返回一个指向本地范围内的C风格数组元素的指针.事情应该出问题.但是,我测试过的编译器都没有抱怨(我用过-Wall -Wextra -pedanticg ++和clang).valgrind也不抱怨.

上面的代码是有效的还是人们会想到的UB?

PS:运行它似乎产生"正确"的结果,即显示"测试",但这并不表示正确性.

c++ memory pointers undefined-behavior

48
推荐指数
1
解决办法
2491
查看次数

为什么仍然需要在using语句的RHS中使用typename消除依赖类型的歧义?

我非常清楚为什么需要使用typename依赖类型,因为当它看到类似的东西时,编译器可能无法消除类型和变量声明之间的歧义T::type,请参阅此答案以获得一个很好的解释.TL; DR:在类似的表达式中T::type * x;,编译器不能"知道" T::type是某个类型,还是在某个特定的特化中声明的变量T.

但是,在类似的东西

using type = T::type;
Run Code Online (Sandbox Code Playgroud)

没有任何暧昧.IMO T::type 应该始终被解析为一个类型,因为它是using语句的RHS的一部分.但是,我们仍然需要在typename这里使用(至少根据gcc和clang),

using type = typename T::type;
Run Code Online (Sandbox Code Playgroud)

Live on Coliru, gcc Live on Coliru, clang

Visual C++ 似乎接受了没有a 的代码typename,但是我对编译器完全符合标准没有太多信心(实际上,它有许多非标准扩展,例如将rvalues绑定到非const引用).

:有什么理由说这不是typenameC++ 11及更高版本规则的例外吗?

c++ language-lawyer c++11

41
推荐指数
1
解决办法
846
查看次数

使用支撑初始化列表时,为什么首选std :: initializer_list构造函数?

考虑一下代码

#include <iostream>

class Foo
{
    int val_;
public:
    Foo(std::initializer_list<Foo> il)
    {
        std::cout << "initializer_list ctor" << std::endl;
    }
    /* explicit */ Foo(int val): val_(val)
    {
        std::cout << "ctor" << std::endl;
    };
};

int main(int argc, char const *argv[])
{
    // why is the initializer_list ctor invoked?
    Foo foo {10}; 
}
Run Code Online (Sandbox Code Playgroud)

输出是

ctor
initializer_list ctor
Run Code Online (Sandbox Code Playgroud)

据我所知,该值10被隐式转换为Foo(第一个ctor输出),然后初始化构造函数启动(第二个initializer_list ctor输出).我的问题是为什么会发生这种情况?标准构造函数Foo(int)不是更好的匹配吗?也就是说,我本来希望这个片段的输出是公正的ctor.

PS:如果我将构造函数标记Foo(int)explicit,则Foo(int)调用唯一的构造函数,因为整数10现在不能隐式转换为a Foo.

c++ constructor initializer-list language-lawyer c++11

30
推荐指数
3
解决办法
2711
查看次数

std :: declval <T>()如何工作?

我试图了解它是如何std::declval<T>()工作的.我知道如何使用它,并知道它的作用,主要是允许你在decltype不构造对象的情况下使用,比如

decltype(std::declval<Foo>().some_func()) my_type; // no construction of Foo
Run Code Online (Sandbox Code Playgroud)

我从cppreference.com知道std::declval<Foo>"添加"一个右值引用Foo,由于引用,折叠规则最终成为右值引用或左值引用.我的问题是为什么Foo没有调用构造函数?如何在std::declval<T>不构建模板参数的情况下实现"玩具"版本?

PS:我知道它与旧技巧不一样

(*(T*)(nullptr))
Run Code Online (Sandbox Code Playgroud)

c++ c++11

29
推荐指数
1
解决办法
8022
查看次数

使用具有尾随返回类型的函数指针

有一些Stack Overflow用户强烈主张在编写函数时总是使用新的C++ 11尾随返回类型约定,例如main()->int.我可以看到优点,因为它使符号统一.但是,当声明一个函数指针时,我找不到任何使用尾随返回形式的方法,即可以声明

typedef int(*fp)(int);

要么

using fp = int(*)(int);

一个函数指针取一个int并返回一个int.

有没有办法在声明这样的函数指针时使用新的尾部返回语法?例如,像

using fp = (*)(int)->int;

但这不编译.如果没有,新语法不适用于函数指针是否有原因?

c++ function-pointers c++11

28
推荐指数
2
解决办法
1103
查看次数

std :: unordered_map :: find使用与Key类型不同的类型?

我有一个unordered_map使用字符串类型作为键:

std::unordered_map<string, value> map;
Run Code Online (Sandbox Code Playgroud)

提供std::hash专业化,也提供string合适的专业化operator==.

现在我还有一个"字符串视图"类,它是一个指向现有字符串的弱指针,避免了堆分配:

class string_view {
    string *data;
    size_t begin, len;
    // ...
};  
Run Code Online (Sandbox Code Playgroud)

现在,我希望能够使用string_view对象检查地图中是否存在密钥.不幸的是, std::unordered_map::find需要一个Key参数,而不是一般T参数.

(当然,我可以"推广"一个到一个string,但这会导致我想避免的分配.)

我喜欢的是类似的东西

template<class Key, class Value>
class unordered_map
{
    template<class T> iterator find(const T &t);
};
Run Code Online (Sandbox Code Playgroud)

这将需要operator==(T, Key)std::hash<T>()适当地定义,并将迭代器返回到匹配值.

有没有解决方法?

c++ unordered-map c++11

27
推荐指数
4
解决办法
4207
查看次数

为什么decltype(auto)会在这里返回引用?

我想(想)我明白了auto.同样的decltype.但是,在C++ 14中,可以有一些像decltype(auto)生成函数的返回类型那样的代数.考虑以下:

decltype(auto) foo()
{
    int m = 1;
    return m;
}
Run Code Online (Sandbox Code Playgroud)

返回类型是int,一切都有意义.

然而,

decltype(auto) foo()
{
    int m = 1;
    return (m);
}
Run Code Online (Sandbox Code Playgroud)

返回int&(即引用int).

我绝对没有想到为什么会发生这种情况,为什么这些括号根本没有任何区别!?希望有人可以对此有所了解.

PS:我也标记过,C++因为有更多的人检查C++标签C++14.

c++ decltype auto c++14

25
推荐指数
1
解决办法
3602
查看次数

如何找到std :: random_device的"真实"熵?

我想std::random_devicestd::random_device::entropy()函数检查我的实现是否具有非零熵(即非确定性).但是,根据cppreference.com

"这个函数在某些标准库中没有完全实现.例如,即使设备是非确定性的,gcc和clang也总是返回零.相比之下,Visual C++总是返回32,而boost.random返回10."

有没有办法找到真正的熵?特别是,现代计算机(MacBook Pro/iMac等)是否具有非确定性源或随机性,例如使用散热监视器?

c++ random c++11

25
推荐指数
2
解决办法
1932
查看次数

是否有使用prvalue的std :: forward的用例?

最常见的用法std::forward是,完美地转发转发(通用)引用,例如

template<typename T>
void f(T&& param)
{
    g(std::forward<T>(param)); // perfect forward to g
}
Run Code Online (Sandbox Code Playgroud)

param是一个lvalue,并std::forward最终将它转换为右值或左值,具体取决于与它有关的参数.

看一下cppreference.com定义,std::forward我发现还有一个rvalue重载

template< class T >
T&& forward( typename std::remove_reference<T>::type&& t );
Run Code Online (Sandbox Code Playgroud)

任何人都可以给我任何rvalue超载的理由吗?我看不到任何用例.如果你想将一个右值传递给一个函数,你可以按原样传递它,不需要std::forward在它上面应用.

这与std::move我不同,我明白为什么人们也想要一个rvalue重载:你可能会处理通用代码,在这些代码中你不知道你传递了什么,你想要无条件支持移动语义,请参阅例如为什么std ::移动采取普遍参考?.

编辑为了澄清这个问题,我问为什么从这里需要重载(2),以及它的用例.

c++ rvalue-reference move-semantics c++11

25
推荐指数
1
解决办法
844
查看次数

显式复制构造函数和统一初始化

显式复制构造函数不允许使用类似的东西Foo foo = bar;,并强制执行复制用法Foo foo(bar);.此外,显式复制构造函数还禁止通过函数的值返回对象.但是,我尝试用大括号替换副本初始化,就像这样

struct Foo
{
    Foo() = default;
    explicit Foo(const Foo&) = default;
};

int main()
{
    Foo bar;
    Foo foo{bar}; // error here
}
Run Code Online (Sandbox Code Playgroud)

我收到了错误(g ++ 5.2)

错误:没有匹配函数来调用'Foo :: Foo(Foo&)'

或(clang ++)

错误:struct initializer中的多余元素

删除explicit使得代码在g ++下可编译,clang ++仍然失败并出现相同的错误(感谢@Steephen).这里发生了什么?统一初始化是否被视为初始化列表构造函数(胜过所有其他构建函数)?但如果是这种情况,为什么程序在复制构造函数非显式时编译?

c++ copy-constructor language-lawyer uniform-initialization c++11

25
推荐指数
1
解决办法
1340
查看次数