小编Pra*_*ian的帖子

从函数返回unique_ptr

unique_ptr<T>不允许复制构造,而是支持移动语义.然而,我可以unique_ptr<T>从函数返回一个并将返回的值赋给变量.

#include <iostream>
#include <memory>

using namespace std;

unique_ptr<int> foo()
{
  unique_ptr<int> p( new int(10) );

  return p;                   // 1
  //return move( p );         // 2
}

int main()
{
  unique_ptr<int> p = foo();

  cout << *p << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码按预期编译和工作.那么该行如何1不调用复制构造函数并导致编译器错误呢?如果我必须使用line 2而不是它有意义(使用line 2也可以,但我们不需要这样做).

我知道C++ 0x允许此异常,unique_ptr因为返回值是一个临时对象,一旦函数退出就会被销毁,从而保证返回指针的唯一性.我很好奇这是如何实现的,它是在编译器中特殊的,还是在语言规范中有一些其他条款可以利用?

c++ unique-ptr c++11

328
推荐指数
6
解决办法
14万
查看次数

如何在C++ 11中正确检查std :: function是否为空?

我想知道如何正确检查是否std::function为空.考虑这个例子:

class Test {
    std::function<void(int a)> eventFunc;

    void registerEvent(std::function<void(int a)> e) {
        eventFunc = e;
    }

    void doSomething() {
        ...
        eventFunc(42);
    }
};
Run Code Online (Sandbox Code Playgroud)

这段代码在MSVC中编译得很好,但如果我在doSomething()没有初始化的情况下调用eventFunc代码,那么显然会崩溃.这是预期的,但我想知道它的价值是eventFunc多少?调试器说'empty'.所以我使用简单的if语句修复了它:

   void doSomething() {
        ...
        if (eventFunc) {
            eventFunc(42);
        }
   }
Run Code Online (Sandbox Code Playgroud)

这有效,但我仍然想知道非初始化的价值是std::function多少?我想写,if (eventFunc != nullptr)std::function(显然)不是指针.

为什么纯净如果有效?它背后的魔力是什么?而且,这是检查它的正确方法吗?

c++ c++11 std-function

87
推荐指数
3
解决办法
5万
查看次数

unique_ptr是否保证在移动后存储nullptr?

unique_ptr保证存储nullptr移动之后?

std::unique_ptr<int> p1{new int{23}};
std::unique_ptr<int> p2{std::move(p1)};
assert(!p1); // is this always true?
Run Code Online (Sandbox Code Playgroud)

c++ unique-ptr move-semantics c++11

72
推荐指数
2
解决办法
7127
查看次数

使用带有clang ++ -stdlib = libc ++的libstdc ++编译库

我在Mac OS X(10.8.2)下使用C++工作,最近我想出了使用C++ 11功能的需求,这些功能可以通过使用libc ++ stdlib的clang ++编译器获得.但是,我还需要使用一些针对libstdc ++编译和链接的遗留库(来自MacPorts).

在这样做时,我得到了链接错误,因为遗留库的标题使用,例如std::string,需要解决std::__1::basic_string(即,libc ++实现std::string)而不是std::basic_string实现.

有没有办法在开发中混合两个库(例如,通过使用一些预处理器标志?)

c++ clang libstdc++ c++11 libc++

68
推荐指数
1
解决办法
2万
查看次数

"向下转换"unique_ptr <Base>到unique_ptr <Derived>

我有一系列工厂回归unique_ptr<Base>.引擎盖下,虽然,他们所提供的指针各种衍生类型,即unique_ptr<Derived>,unique_ptr<DerivedA>,unique_ptr<DerivedB>

鉴于DerivedA : Derived并且Derived : Base我们有:

unique_ptr<Base> DerivedAFactory() {
    return unique_ptr<Base>(new DerivedA);
}
Run Code Online (Sandbox Code Playgroud)

我需要做的是将指针从返回"转换" unique_ptr<Base>到某个派生级别(不一定是原始的内部级别).用伪代码说明:

unique_ptr<Derived> ptr = static_cast<unique_ptr<Derived>>(DerivedAFactory());
Run Code Online (Sandbox Code Playgroud)

我正在考虑通过从中释放对象unique_ptr,然后使用一个转换原始指针的函数并将其重新分配给另一个unique_ptr所需的风格(release在调用之前由调用者显式完成)来实现这一点:

unique_ptr<Derived> CastToDerived(Base* obj) {
    return unique_ptr<Derived>(static_cast<Derived*>(obj));
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,还是/会有什么时髦吗?


PS.还有一个复杂的问题是,有些工厂驻留在运行时动态加载的DLL中,这意味着我需要确保生成的对象在创建它们的同一个上下文(堆空间)中被销毁.所有权的转移(通常发生在另一个上下文中)必须从原始上下文中提供删除.但除了必须与指针一起提供/转换删除器之外,铸造问题应该是相同的.

c++ smart-pointers factory-pattern unique-ptr c++11

56
推荐指数
1
解决办法
2万
查看次数

为什么这段代码在没有类型不匹配错误的情况下编译(C++ 11)?

std::vector<char> p = {"abc", "def"};
Run Code Online (Sandbox Code Playgroud)

"abc"并且"def"不是char,为什么编译器没有给我一个关于这种类型不匹配的错误?

c++ c++11 list-initialization

45
推荐指数
1
解决办法
1656
查看次数

C++ std :: unique_ptr:为什么lambdas没有任何大小的费用?

我正在阅读"Effective Modern C++".在与std::unique_ptr它相关的项目中声明如果自定义删除器是无状态对象,则不会出现大小费用,但如果它是函数指针或std::function大小费用发生.你能解释一下原因吗?

假设我们有以下代码:

auto deleter_ = [](int *p) { doSth(p); delete p; };
std::unique_ptr<int, decltype(deleter_)> up(new int, deleter_);
Run Code Online (Sandbox Code Playgroud)

根据我的理解,unique_ptr应该有一个类型的对象decltype(deleter_)并分配deleter_给该内部对象.但显然这不是正在发生的事情.你能用最小的代码示例来解释这背后的机制吗?

c++ unique-ptr c++11 c++14

41
推荐指数
4
解决办法
3235
查看次数

ANSI C中的parens表达式包含复合语句(块)吗?

浏览Linux内核源代码时,我发现了一段代码,其中括号括起来的语句块被视为表达式a laisp(或ML),即表达式,其值是最后一个语句的值.

例如:

int a = ({
    int i;
    int t = 1;
    for (i = 2; i<5; i++) {
        t*=i;
    }
    t;
});
Run Code Online (Sandbox Code Playgroud)

我一直在研究ANSI C语法,试图弄清楚这段代码如何适合解析树,但我还没有成功.

那么,有没有人知道这种行为是由标准规定还是只是GCC的特殊性?

更新:我已尝试使用标志-pedantic,编译器现在给我一个警告:

warning: ISO C forbids braced-groups within expressions
Run Code Online (Sandbox Code Playgroud)

c standards gcc expression

37
推荐指数
2
解决办法
7507
查看次数

initializer_list和模板类型推导

考虑功能:

template<typename T>
void printme(T&& t) {
  for (auto i : t)
    std::cout << i;
}
Run Code Online (Sandbox Code Playgroud)

或任何其他期望一个参数具有begin()/ end()启用类型的函数.

以下为什么违法?

printme({'a', 'b', 'c'});

当所有这些都合法时:

printme(std::vector<char>({'a', 'b', 'c'}));
printme(std::string("abc"));
printme(std::array<char, 3> {'a', 'b', 'c'});
Run Code Online (Sandbox Code Playgroud)

我们甚至可以这样写:

const auto il = {'a', 'b', 'c'};
printme(il);
Run Code Online (Sandbox Code Playgroud)

要么

printme<std::initializer_list<char>>({'a', 'b', 'c'});
Run Code Online (Sandbox Code Playgroud)

c++ templates initializer-list c++11

34
推荐指数
3
解决办法
7447
查看次数

在C++ 11中延迟启动一个线程

我正在进入C++ 11线程并遇到了问题.

我想将一个线程变量声明为全局并稍后启动它.

然而,我见过的所有例子似乎都是立即启动线程的

thread t(doSomething);
Run Code Online (Sandbox Code Playgroud)

我想要的是

thread t;
Run Code Online (Sandbox Code Playgroud)

并稍后启动该帖子.

我试过的是

if(!isThreadRunning)
{
    thread t(readTable);
}
Run Code Online (Sandbox Code Playgroud)

但现在是块范围.所以我想声明t然后稍后启动线程,以便其他函数可以访问t.

谢谢你的帮助.

c++ multithreading c++11

33
推荐指数
2
解决办法
2万
查看次数