小编lub*_*bgr的帖子

标准库或编译器在哪里利用 noexcept 移动语义(向量增长除外)?

移动操作应该是noexcept;首先是直观和合理的语义。第二个参数是运行时性能。来自核心指南C.66,“使移动操作 noexcept”:

投掷动作违反了大多数人的合理假设。标准库和语言设施将更有效地使用非投掷动作。

本指南性能部分的典型示例是std::vector::push_back朋友需要增加缓冲区的情况。标准在这里需要一个强大的异常保证,如果是这样,这只能将元素移动构造到新缓冲区中noexcept- 否则,必须复制它。我明白了,差异在基准测试中是可见的。

然而,除此之外,我很难找到noexcept移动语义对性能产生积极影响的真实证据。浏览标准库 ( libcxx+ grep),我们看到它std::move_if_noexcept存在,但它几乎没有在库本身中使用。同样,std::is_noexcept_swappable仅用于充实条件noexcept限定符。这与现有声明不符,例如 Andrist 和 Sehr 的“C++ High Performance”中的声明(第二版,第 153 页):

所有算法都在移动元素时使用std::swap()and std::move(),但前提是移动构造函数和移动赋值标记为 noexcept。因此,在使用算法时为重物实现这些很重要。如果它们不可用且无异常,则将复制元素。

把我的问题分成几部分:

  1. 标准库中是否有类似于 , 的代码路径在std::vector::push_back输入std::is_nothrow_move_constructible类型时运行得更快?
  2. 我认为书中引用的段落不正确是否正确?
  3. 是否有一个明显的例子来说明当类型符合noexcept指南时,编译器何时能够可靠地生成运行时效率更高的代码?

我知道第三个可能有点模糊。但是如果有人能想出一个简单的例子,那就太好了。

c++ performance stl move-semantics

12
推荐指数
1
解决办法
503
查看次数

Herb Sutter在GotW#35中关于类型名称的代码玩笑是否过时?

我读的文章周的老大师之一typename#35。最后,您可以找到以下代码段:

#include <iostream>
using std::cout;
using std::endl;

struct Rose {};

struct A { typedef Rose rose; };

template<class T>
struct B : T { typedef typename T::rose foo; };

template<class T>
void smell( T ) { cout << "awful" << endl; }

void smell( Rose ) { cout << "sweet" << endl; }

int main() {
    smell( A::rose() );
    smell( B<A>::foo() );
}
Run Code Online (Sandbox Code Playgroud)

我不明白 我的第一个猜测是,第二次smell调用导致模板smell被实例化,原因是您容易忽略了一些东西(笑话应该是什么,否则?!)。但是这两个调用都导致打印出“甜”字。毕竟这不是意料之中的吗?在中typedef Rose rose;Rose不是依赖名称,所以很好。在typedef …

c++ typename

9
推荐指数
1
解决办法
170
查看次数

Variadic template wrapper around tuple

I am currently in the process of updating my language knowledge (to C++17). I was trying to get this code to compile using gcc and couldn't figure it out so I tried MSVC and clang and both seem okay with this code -- is there anything wrong with this bit of code?

gcc seems to be complaining about instantiating a tuple<> with no template parameters which is odd:

prog.cc: In instantiation of 'C::C(U&& ...) [with U = {const A&, const …

c++ c++17

7
推荐指数
0
解决办法
100
查看次数

调用带有std :: function作为lambda参数的函数

我从这里获得的问题的依据是: 无法从lambda函数推断出模板参数std :: function 。此线程中的问题是:为什么此代码无法将lambda传递给函数:

#include <iostream>
#include <functional>

template <typename T>
void call(std::function<void(T)> f, T v)
{
    f(v);
}

int main(int argc, char const *argv[])
{
    auto foo = [](int i) {
        std::cout << i << std::endl;
    };
    call(foo, 1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该线程的答案是,因为lambda不是a std::function。但是为什么这段代码会编译:

#include <iostream>
#include <functional>

template <typename T>
void call(std::function<void(T)> f, T v)
{
    f(v);
}

int main(int argc, char const *argv[])
{
    auto foo = [](int i) {
        std::cout << i << std::endl; …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

6
推荐指数
1
解决办法
95
查看次数

为什么允许将自身重新解释为整数,枚举和成员指针类型?

In this recent question, we saw that it's not allowed to reinterpret_cast some custom class type instance to itself; struct A{}; reinterpret_cast<A>(A{}); is invalid (it works only through references or pointers). Which seems to make sense, because of the lack of real-world scenarios where such identity conversion is necessary.

Checking the corresponding standard clause, we have in [expr.reinterpret.cast] (emphasis mine):

1 [...] Conversions that can be performed explicitly using reinterpret_­cast are listed below. No other conversion can be performed …

c++ language-lawyer reinterpret-cast

6
推荐指数
1
解决办法
93
查看次数

为什么动态转换只适用于引用和指针

为什么动态转换仅适用于指针和引用?说我有这样的东西

struct foo
{
    virtual void test(){}
};
struct bar : public foo
{
};
Run Code Online (Sandbox Code Playgroud)

为什么这样的东西不起作用

foo* f = new bar();
bar& b = dynamic_cast<bar>(*f); //Fail must be either pointer or reference
Run Code Online (Sandbox Code Playgroud)

现在假设bar它的父级 foo 确实有一个转换构造函数。我的问题是为什么动态转换只接受指针和引用而不是像这样的简单对象static_cast

c++ casting

5
推荐指数
1
解决办法
1488
查看次数

C ++ Lambda函数-与目标相比如何返回最接近的向量元素

我有一个已经排序的向量,称为ve​​c,还有一个目标变量。目标是返回最接近目标的向量元素。

我试图将C ++ 11 lambda函数与[=]一起使用以捕获外部变量

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> vec{1,2,3,4,5};
    double target = 3.14159;

    int res = min(vec.begin(), vec.end(), [=](int v1, int v2) -> bool {
            return abs(v1-target) < abs(v2-target);
        });

    cout << res << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望得到res = 3,但是会返回错误:

error: cannot convert 'const __gnu_cxx::__normal_iterator<int*, std::vector<int> >' to 'int' in initialization
Run Code Online (Sandbox Code Playgroud)

c++ lambda comparator c++11

5
推荐指数
1
解决办法
115
查看次数

如果make_shared / make_unique可以抛出bad_alloc,为什么不尝试使用try catch块呢?

make_shared的CppReference页面说(与make_unique相同)

可能引发std :: bad_alloc或T的构造函数引发的任何异常。如果引发异常,则这些函数无效。

这意味着在失败的情况下可以引发std :: bad_alloc接收。“函数无效”暗含意味着它无法返回nullptr。如果是这种情况,为什么不总是将make_shared / make_unique始终写入try catch块中是一种惯例?

使用make_shared的正确方法是什么?在尝试捕获块内?或检查nullptr?

c++ exception smart-pointers nullptr c++11

5
推荐指数
1
解决办法
209
查看次数

如何(eval ...)在鸡 r7rs 库中?

我正在尝试获得evalr7rs鸡蛋库中工作的基本知识。以下顶级(不是库)程序按我的预期工作,运行时csi -R r7rs

(import (scheme base)
        (scheme eval))

(eval '42 (scheme-report-environment 5))
Run Code Online (Sandbox Code Playgroud)

这也适用于(null-environment 5)(但不适用于(environment '(scheme base) ...)变体)。但是,在库中:

(define-library (test-eval)
  (import
    (scheme base)
    (scheme eval))
  (export
    my-eval)
  (begin
    (define (my-eval)
      (eval '42 (scheme-report-environment 5)))))
Run Code Online (Sandbox Code Playgroud)

我得到

Error: module unresolved: test-eval
....
<syntax>          [my-eval] (scheme-report-environment 5)
<syntax>          (##core#begin)
<syntax>          (##core#undefined)    <--
Run Code Online (Sandbox Code Playgroud)

可能是什么问题呢?Wiki 中的R7RS 环境似乎存在一些问题,但我不确定这是否与此处相关。

用鸡 5.2.0 版(自制程序包)测试,两者csicsc.

scheme chicken-scheme r7rs

5
推荐指数
1
解决办法
171
查看次数

从C ++ 17之前的初始值设定项推导的std :: vector类型... C ++ 11的任何解决方法?

我从C ++ 17了解到,借助推论指南,可以从例如初始化中推导std :: vector的模板参数:

std::vector vec = { function_that_calculate_and_return_a_specifically_templated_type() }
Run Code Online (Sandbox Code Playgroud)

但是,我现在不想编译和运行代码的机器上没有C ++ 17的支持。

C ++ 11是否有任何可能的解决方法?如果存在更多解决方案,那么最好的解决方案就是保持代码的可读性。

目前,我唯一的想法是跟踪代码中的各种情况(幸运的是,它们不应太多)并进行一些显式的typedef / using。

任何建议都非常欢迎

c++11

4
推荐指数
1
解决办法
130
查看次数