如果我理解正确,a weak_ptr不会增加托管对象的引用计数,因此它不代表所有权.它只是让您访问一个对象,其生命周期由其他人管理.所以我真的不明白为什么一个weak_ptr不能用a构建unique_ptr,而只能用a 构建shared_ptr.
有人能简单解释一下吗?
在我看到CppCon 2015的这个演讲之后,我想对一些程序进行概述.我下载了那个人在谈话中使用的相同Google基准库,用适当的开关编译我的程序,将其链接到它,然后使用perf记录一次跑步.报告选项给了我这个:
正如您所看到的,函数名称不是很易读.我认为这与C++名称修改有关.有趣的是,所有的功能名称都在视频中正确显示给那个发表演讲的人,但不适合我.我不认为这是完全缺少符号信息的情况,因为在这种情况下我只会看到内存地址.由于某种原因,perf不能"撤消"我的C++名称,这看起来很令人沮丧.
我正在使用gcc(g ++)版本5.2.1,perf是版本4.2.6,我在编译时使用这些开关:
-I<my own include path> -L<path to the benchmark library> -O3 -std=c++14 -gdwarf-2 -fno-rtti -Wall -pedantic -lbenchmark -pthread
我不使用的原因-fno-omit-frame-pointer是我使用了-gdwarf-2选项,它将调试信息留在矮人可执行文件中,这是在这种情况下保留帧指针的替代方法.这也意味着我--call-graph "dwarf"转到了perf record.无论如何,我也尝试了帧指针方法,它给出了相同的结果,所以这并不重要.
那么为什么在这种情况下不会"撤消"C++名称错误?这与使用GCC有什么关系,这当然意味着我正在使用libstdc ++?
因此,C++ 14引入了许多用户定义的文字,其中一个是用于创建对象的"s"文字后缀std::string.根据文档,它的行为与构造std::string对象完全相同,如下所示:
auto str = "Hello World!"s; // RHS is equivalent to: std::string{ "Hello World!" }
Run Code Online (Sandbox Code Playgroud)
当然,构建一个未命名的std::string对象可以在C++ 14之前完成,但由于C++ 14的方式简单得多,我认为实际上会有更多的人考虑std::string在现场构建对象,这就是为什么我认为有必要提问这个.
所以我的问题很简单:在什么情况下构建一个未命名的std::string对象是一个好的(或坏的)想法,而不是简单地使用C风格的字符串文字?
考虑以下:
void foo(std::string arg);
foo("bar"); // option 1
foo("bar"s); // option 2
Run Code Online (Sandbox Code Playgroud)
如果我是正确的,第一个方法将调用适当的构造函数重载std::string来在foo范围内创建一个对象,第二个方法将首先构造一个未命名的字符串对象,然后foo从中移动构造的参数.虽然我确信编译器非常擅长优化这样的东西,但是,第二个版本似乎需要额外的移动,而不是第一个替代(当然不像移动是昂贵的).但同样,在使用合理的编译器编译之后,最终结果最有可能被高度优化,并且无论如何都没有冗余和移动/复制.
另外,如果foo被重载以接受右值引用怎么办?在那种情况下,我认为打电话是有意义的foo("bar"s),但我可能是错的.
考虑以下:
std::cout << "Hello World!" << std::endl; // option 1
std::cout << "Hello World!"s << std::endl; // option 2
Run Code Online (Sandbox Code Playgroud)
在这种情况下,std::string对象可能cout通过右值引用传递给运算符,第一个选项可能传递指针,因此两者都是非常便宜的操作,但第二个选项首先需要额外构建对象.这可能是一种更安全的方式(?). …
我想枚举场景中的所有节点.不仅是场景本身的孩子,还有那些孩子,以及那些孩子的孩子......所以我希望能够通过整个节点层次结构.
有没有一种方法可以在不知道节点树有多深的情况下做到这一点?
这是我测试的代码:
#include <iostream>
#include <chrono>
using namespace std;
#define CHRONO_NOW chrono::high_resolution_clock::now()
#define CHRONO_DURATION(first,last) chrono::duration_cast<chrono::duration<double>>(last-first).count()
int fib(int n) {
if (n<2) return n;
return fib(n-1) + fib(n-2);
}
int main() {
auto t0 = CHRONO_NOW;
cout << fib(45) << endl;
cout << CHRONO_DURATION(t0, CHRONO_NOW) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,有更快的方法来计算斐波纳契数,但这是一个很好的小压力测试,专注于递归函数调用.除了使用计时器测量时间之外,代码没有别的了.
首先,我在OS X上的Xcode中运行了几次测试(这样就是铿锵声),使用-O3优化.跑了大约9秒钟.
然后,我在Ubuntu上使用gcc(g ++)编译了相同的代码(再次使用-O3),该版本只用了大约6.3秒就可以运行了!此外,我在我的Mac上运行VirtualBox内部的 Ubuntu ,这只会对性能产生负面影响,如果有的话.
你去吧:
在OS X上克服 - > ~9秒
在VirtualBox中的 Ubuntu 上的 gcc - > ~6.3秒.
我知道这些是完全不同的编译器,所以他们做的事情不同,但我看到的所有gcc和clang的测试只显示出更少的差异,在某些情况下,差异是另一种方式(clang更快) ).
因此,在这个特定的例子中,为什么gcc能够以英里数击败?
我想写C++中的TCP/IP服务器(使用bind(),accept()可以处理多个客户端连接到它在同一时间等).我已经阅读了一些关于此的主题,每个人都建议如下(脏的伪代码即将出现):
set up server, bind it
while (1) {
accept connection
launch new thread to handle it
}
Run Code Online (Sandbox Code Playgroud)
哪个在具有多个线程的机器上完全正常工作.但我的目标系统是没有任何硬件线程的单核机器.为了进行一点测试,我尝试std::thread在系统上启动多个线程,但它们是一个接一个地执行的.没有平行的善良:(
这使得无法实现上述算法.我的意思是,我确信它可以完成,我只是不知道如何,所以我真的很感激任何帮助.
我在网站上检查了类似的问题,但我找不到符合我的情况的任何内容.这是我试图运行的代码(需要C++ 14):
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
class countdownTimer {
public:
using duration_t = chrono::high_resolution_clock::duration;
countdownTimer(duration_t duration) : duration{ duration }, paused{ true } {}
countdownTimer(const countdownTimer&) = default;
countdownTimer(countdownTimer&&) = default;
countdownTimer& operator=(countdownTimer&&) = default;
countdownTimer& operator=(const countdownTimer&) = default;
void start() noexcept {
if (started) return;
startTime = chrono::high_resolution_clock::now();
endTime = startTime + duration;
started = true;
paused = false;
}
void pause() noexcept {
if (paused || !started) return;
pauseBegin = chrono::high_resolution_clock::now();
paused …Run Code Online (Sandbox Code Playgroud) 这段代码当然是愚蠢的,但是我只是为了说明问题编写了代码。这里是:
#include <iostream>
using namespace std;
struct foo {
int a = 42;
template <typename T>
operator T* () {
cout << "operator T*()\n";
return reinterpret_cast<T*>(&a);
}
template <typename T>
operator const T* () const {
cout << "operator const T*() const\n";
return reinterpret_cast<const T*>(&a);
}
template <typename T>
T get() {
cout << "T get()\n";
return this->operator T();
}
};
int main() {
foo myFoo;
cout << *myFoo.get<const int*>() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
使用Visual Studio 2019(ISO C ++ 17,/Ox …
考虑以下课程:
class foo {
int data;
public:
template <typename T, typename = enable_if_t<is_constructible<int, T>::value>>
foo(const T& i) : data{ i } { cout << "Value copy ctor" << endl; }
template <typename T, typename = enable_if_t<is_constructible<int, T>::value>>
foo(T&& i) : data{ i } { cout << "Value move ctor" << endl; }
foo(const foo& other) : data{ other.data } { cout << "Copy ctor" << endl; }
foo(foo&& other) : data{ other.data } { cout << "Move ctor" << endl; …Run Code Online (Sandbox Code Playgroud) 考虑以下类,就像一个简单的例子:
#include <iostream>
#include <string>
using namespace std;
class point {
public:
int _x{ 0 };
int _y{ 0 };
point() {}
point(int x, int y) : _x{ x }, _y{ y } {}
operator string() const
{ return '[' + to_string(_x) + ',' + to_string(_y) + ']'; }
friend ostream& operator<<(ostream& os, const point& p) {
// Which one? Why?
os << static_cast<string>(p); // Option 1
os << p.operator string(); // Option 2
return os;
}
};
Run Code Online (Sandbox Code Playgroud)
是否应该直接调用转换运算符,或者只是调用static_cast …
所以在Swift中,有什么区别
var arr = ["Foo", "Bar"] // normal array in Swift
Run Code Online (Sandbox Code Playgroud)
和
var arr = NSMutableArray.array() // 'NSMutableArray' object
["Foo", "Bar"].map {
arr.addObject($0)
}
Run Code Online (Sandbox Code Playgroud)
除了是同一件事的不同实现.两者似乎都具有可能需要的所有基本功能(.count插入/移除对象等的能力).
NSMutableArray是在Obj-C时代发明的,显然是为了提供更现代的解决方案,而不是常规的C风格阵列.但它与Swift的内置阵列相比如何呢?
哪一个更安全和/或更快?
我在以下场景中:
struct container {
data* ptr;
};
void someFunc(container* receiver /* wants to be filled */) {
auto myData = createData(); // returns shared_ptr<data>
receiver->ptr = myData.get();
}
Run Code Online (Sandbox Code Playgroud)
生成该数据的函数和接收它的对象是两个不同库的一部分,我无法修改它的源代码.我必须使用这些数据类型,我无能为力.
所以我必须实现一个获取一些数据的函数,然后将指向该数据的指针传递给一个对象.我的问题是创建我的数据的函数,返回一个shared_ptr实例.需要数据的对象只接受指向它的原始指针.
如您所见,我调用get()它shared_ptr来获取原始指针并将其传递给接收对象.如果我没有弄错,那么shared_ptr只要它超出范围,就会减少引用计数.所以在这种情况下,这意味着它会在函数返回时立即销毁我的数据,因为引用计数将达到0.
那么如何在shared_ptr不破坏托管对象的情况下摆脱实例呢?我传递数据的对象(为简单起见用"容器"结构说明)确实在其析构函数中处理内存清理,因此我不需要任何引用计数或类似的东西.我不想再监视分配的数据(除了接收指向它的指针的对象).我想摆脱它shared_ptr,并且只有一个指向已分配数据的原始指针,我可以将其传递给接收对象.
那可能吗?
想象一下这样的一个类:
class foo {
public:
foo() : _bar{new bar}, _baz{new baz} {}
private:
unique_ptr<bar> _bar;
unique_ptr<baz> _baz;
};
Run Code Online (Sandbox Code Playgroud)
因此,每当一个foo被破坏的实例被破坏时,它的数据成员将以什么顺序被销毁,如果这个被定义的行为呢?
让我们说这_baz取决于它的存在_bar,也许它使用了一些_bar拥有的资源(让我们假设它知道_bar对象,即使构造函数没有反映这一点).所以在这种情况下,如果_bar首先被破坏(当它被破坏的时候foo),那么_baz可能会尝试访问已经被_bar析构函数释放的一些资源.
一个显而易见的解决方案是实现一个析构函数foo,它可以手动释放_baz并按_bar正确的顺序,但是如果没有实现析构函数呢?是否存在定义数据成员的销毁顺序的默认行为?
c++ ×11
clang ×2
shared-ptr ×2
arrays ×1
c++-chrono ×1
c++14 ×1
c-strings ×1
casting ×1
const ×1
constructor ×1
destructor ×1
enable-if ×1
gcc ×1
ios ×1
networking ×1
objective-c ×1
perf ×1
performance ×1
profiling ×1
sockets ×1
sprite-kit ×1
static-cast ×1
stdstring ×1
string ×1
swift ×1
tcp ×1
unique-ptr ×1
weak-ptr ×1
x86 ×1