小编nos*_*sid的帖子

为什么basic_string :: swap不是noexcept?

我刚刚发现basic_string的两个交换函数(命名空间std中的成员函数和函数)没有用noexcept声明- 既不是在GCC-4.8的标准库中也不是在最新的C++草案N3690中.

另一方面,移动构造函数以及移动赋值运算符使用noexcept声明.这表明应该可以提供noexcept交换功能.

问题:没有使用noexcept声明交换函数的原因是什么?

更新:问题是我想在我自己的交换函数中使用模板函数,它使用static_assert检查交换是否实际上是noexcept,例如:

struct foo {
    bar_t bar;
    baz_t baz;
    void swap(foo& rhs) noexcept {
        swap_noexcept(bar, rhs.bar);
        swap_noexcept(baz, rhs.baz);
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,只有在使用noexcept声明交换函数时才有效,但情况并非如此basic_string.

c++ c++11

21
推荐指数
1
解决办法
990
查看次数

Linux零拷贝:使用vmsplice在两个进程之间传输内存页面

目前,我试图了解splice/vmsplice的价值.关于IPC的用例,我在stackoverflow上偶然发现了以下答案:https://stackoverflow.com/a/1350550/1305501

问题:如何使用vmsplice将内存页面从一个进程转移到另一个进程而不复制数据(即零拷贝)?

上面提到的答案声称它是可能的.但是,它不包含任何源代码.如果我理解vmsplice正确的文档,如果内存被正确分配和对齐,以下函数将把内存页面转移到管道(内核缓冲区)而不复制.为了便于演示而省略了错误处理.

// data is aligned to page boundaries,
// and length is a multiple of the page size
void transfer_to_pipe(int pipe_out, char* data, size_t length)
{
    size_t offset = 0;
    while (offset < length) {
        struct iovec iov { data + offset, length - offset };
        offset += vmsplice(pipe_out, &iov, 1, SPLICE_F_GIFT);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是如何在不复制的情况下从用户空间访问内存页面?显然,以下方法不起作用:

  • vmsplice:此功能也可用于反向.但根据内核源代码中的注释,数据将被复制.
  • read:我可以想象,如果内存正确对齐,这个函数会产生一些魔力,但我对此表示怀疑.
  • mmap:管道不可能.但是有没有可以使用的某种虚拟文件,即splice虚拟文件的内存页面mmap呢?
  • ......?

根本不可能vmsplice吗?

c linux virtual-memory splice

20
推荐指数
1
解决办法
6288
查看次数

std :: unordered_set <T> :: insert(T &&):如果存在,则移动参数

这个问题是关于C++ 11标准库中几个函数的规范,它们将它们的参数作为右值引用,但不要在所有情况下都使用它们.一个例子是 std::unordered_set<T>::insert(T&&).

很明显,这个方法将使用移动构造函数T来构造容器中的元素(如果它尚不存在).但是,如果元素已经存在于容器中会发生什么?我很确定在这种情况下没有理由改变对象.但是,我没有在C++ 11标准中找到支持我的声明的任何内容.

这是一个示例,说明为什么这可能很有趣.以下代码从std :: cin读取行并删除第一次出现的重复行.

std::unordered_set<std::string> seen;
std::string line;
while (getline(std::cin, line)) {
    bool inserted = seen.insert(std::move(line)).second;
    if (!inserted) {
        /* Is it safe to use line here, i.e. can I assume that the
         * insert operation hasn't changed the string object, because 
         * the string already exists, so there is no need to consume it. */
        std::cout << line << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,这个例子适用于GCC 4.7.但我不确定,根据标准是否正确.

c++ c++11

16
推荐指数
1
解决办法
754
查看次数

我应该为赋值运算符使用左值引用限定符吗?

最近,我跟着讨论了C++中表达式的赋值,如下例所示:

string s1, s2, s3;
(s1 + s2) = s3;
Run Code Online (Sandbox Code Playgroud)

使用C++ 11,可以将赋值运算符限制为左值引用(在左侧).当声明赋值运算符如下时,由于类型不兼容,编译器Clang拒绝带有错误消息的代码.

auto operator=(const string& rhs) & -> string&;
auto operator=(string&& rhs) & -> string&;
Run Code Online (Sandbox Code Playgroud)

我没有在任何地方见过这个.是否有充分的理由不为赋值运算符使用左值引用限定符(除了在大多数编译器中缺少支持)?

c++ operator-overloading assignment-operator c++11

14
推荐指数
2
解决办法
1215
查看次数

std :: pair:限制性过强的构造函数?

我偶然发现了新std::pair构造函数的一个令人惊讶的行为,这是C++ 11引入的.我在使用时观察到了这个问题std::pair<int, std::atomic<int>>,并且它发生了,因为std::atomic它既不可复制也不可移动.在下面的代码,我取代std::atomic<int>foobar了简化.

下面的代码编译很好,包括GCC-4.9和Clang-3.5(有和没有libc ++):

struct foobar
{
    foobar(int) { } // implicit conversion
    // foobar(const foobar&) = delete;
};

std::pair<int, foobar> p{1, 2};
Run Code Online (Sandbox Code Playgroud)

此行为是预期的.但是,当我删除复制构造函数时foobar,编译失败.它适用于分段构造,但我认为这不应该是必要的,因为隐式转换intfoobar.我指的是具有以下签名的构造函数:

template <typename U, typename V>
pair(U&& u, V&& v);
Run Code Online (Sandbox Code Playgroud)

你能解释为什么对构造函数是如此限制,并且不允许对noncopyable/nonmovable类型进行隐式转换?

c++ c++11

13
推荐指数
1
解决办法
2744
查看次数

闲置的线程=坏?

我想在一小组机器上支持大约10,000个并发HTTP客户端(尽可能小).我想在用户使用应用程序时保持与每个客户端的连接,以允许服务器推送更新.

我相信通常建议将async IO用于这些长期连接,以避免大量线程处于空闲状态.但线程闲置有什么问题?我发现线程模型在精神上更容易使用,但我不想做一些会让我头疼的事情.我想我将不得不进行实验,但我想知道是否有人知道以前的这些实验中的任何实验?

java multithreading asynchronous nio c10k

11
推荐指数
1
解决办法
2154
查看次数

为什么不链接java.util.stream.Stream#forEach

在java 8中,java.util.stream.Stream#forEach考虑作为传统for循环的替代.但为什么不是这不是链函数.它返回虚空而不是Stream<T>自我.

像这样

Arrays
    .stream(Girls.toArray())
    .forEach(Girls::getUp)
    .forEach(Girls::dressUp)
    .filter(/* Top 10 Girls */)
    .forEach(Gay.getMe()::gotGirl)
    .endFilter()// Not an API, but it means remove last filter
    .filter(/* Worst 10 Girls */)
    .forEach(Gay.get(0)::gotGirl)


girls = Arrays
    .stream(Girls.toArray());
girls.forEach(g->{g.getUp();g.dressUp()});
girls.filter(/* Top 10 Girls */)
    .forEach(Gay.getMe()::gotGirl);
girls.filter(/* Worst 10 Girls */)
    .forEach(Gay.get(0)::gotGirl);
Run Code Online (Sandbox Code Playgroud)

第一个比第二个好.但是第一个表现更差.

那么,为什么forEach不能连锁?

java java-8

9
推荐指数
4
解决办法
4087
查看次数

具有不同arities的重载方法的方法引用无效

尝试编译表达式时Comparator.comparing(String::toLowerCase),Java编译器返回错误.有关更多信息,请参阅以下问题:

为什么Comparator.comparing不能与String :: toLowerCase方法引用一起使用?


我试图尽可能地减少这个问题.特别是,我已经删除了几乎所有依赖项到其他类.的主要方法包括两个方法调用.第一个语句编译时没有错误,而第二个语句产生错误.

interface Fun<T, R> { R apply(T t); }

public final class Foo {
    public static void main(String... args) {
        invoke(Foo::bar); // OK
        invoke(Foo::baz); // ERROR
    }
    private static <T, U> void invoke(Fun<T, U> f) { }
    private String bar() { return null; }
    private String baz() { return null; }
    private String baz(Integer i, Integer j) { return null; }
}
Run Code Online (Sandbox Code Playgroud)

这很奇怪,因为第二个baz方法不适用于此上下文,因为参数数量不匹配.我看了JLS8(15.13).但是,它没有帮助,因为方法引用的规则非常复杂.

问:为什么第二种情况会出现编译错误?根据JLS真的会出现编译错误吗?根据对另一个问题的一些评论,Netbeans中没有编译错误.


作为参考,我使用的是JDK8版本1.8.0-b132.如果在命令行上编译程序,编译器将显示以下错误消息:

$ /opt/jdk8/bin/javac Foo.java
Foo.java:6: …
Run Code Online (Sandbox Code Playgroud)

java type-inference java-8 method-reference

7
推荐指数
1
解决办法
2534
查看次数

如何用vstring替换std :: string?

我最近了解到,自几年以来,libstdc ++库包含vstring(也称为versa_string),它提供了相同的功能std::string,但显然更符合C++标准.我曾试图用它vstring作为替代品std::string,但我发现没有简单的方法可以做到.

有没有一种简单的方法来代替std::stringvstring,在不改变的libstdc ++源代码?

我可以用std::string别名替换代码中的所有用法,如下面的清单所示.然而,这种方法的问题在于,它std::string也在某些地方内部使用,例如在std::ostringstream.这意味着,这些陈述std::ostringstream os; my::string s = os.str();不再适用.

namespace my {
#ifdef __GLIBCXX__
    using string = __gnu_cxx::__vstring;
#else
    using string = std::string;
#endif
}
Run Code Online (Sandbox Code Playgroud)

c++ string libstdc++ c++11

7
推荐指数
1
解决办法
1329
查看次数

性能std :: strstr vs. std :: string :: find

可能重复:
C++ string :: find complexity

最近我注意到这个函数std::string::find比函数慢了一个数量级std::strstr- 在我的环境中使用Linux上的GCC 4.7.性能差异取决于字符串的长度和硬件架构.

差异似乎有一个简单的原因:std::string::find基本上是std::memcmp在一个循环中调用- 具有时间复杂性O(m * n).相比之下,std::strstr它针对硬件架构进行了高度优化(例如,使用SSE指令),并使用更复杂的字符串匹配算法(显然是Knuth-Morris-Pratt).

我也很惊讶没有在语言文件中找到这两个功能的时间复杂性(即草稿N3290和N1570).我只发现了时间的复杂性char_traits.但这没有用,因为没有子字符串搜索功能char_traits.

我希望,这std::strstrmemmem含有类似优化几乎相同的性能.直到最近,我认为内部std::string::find使用memmem.

问题是:有什么好的理由,为什么std::string::find不使用std::memmem?它在其他实现中有所不同吗?

问题不是:这个功能的最佳实现是什么?如果它比C慢,那么对C++来说真的很难说.如果两个实现都很慢,我就无所谓了.真正伤害的是性能差异.

c++ gcc stdstring strstr

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