据我所知,5.2.9静态void*强制转换中的措辞,唯一一次允许对象 - 指针转换void*的结果是第一次出现逆转换的结果.
在整个标准中,有一堆对指针表示的引用,并且指针的表示与指针的表示void相同char,依此类推,但它似乎从未明确表示投射任意void指针会产生指针在内存中的相同位置,具有不同的类型,非常类似于类型 - 惩罚是未定义的,而不是回到对象的实际类型.
因此,虽然malloc清楚地返回合适内存的地址等等,但就我所见,似乎没有任何方法可以实际使用它.
我刚刚在工作中构建了一个项目,我看到添加了一个新功能:
const std::string& ClassName::MethodName() const
{
return "";
}
Run Code Online (Sandbox Code Playgroud)
编译器发出警告:
警告C4172:返回本地变量的地址或临时变量
我认为编译器是对的.这个功能有多安全?
请注意,const char*由于字符串文字具有静态存储持续时间,因此函数不会返回哪个是正常的.它返回一个引用const std::string
我有一个Delphi表单,它提供了一个接口对象背后的功能,代码的其他部分也通过属于Form的属性获得引用.我无法将接口功能委托给子对象,因为窗体上的控件/组件提供了太多的功能.我不能使用TAggregatedObject或TContainedObject来链接传递给接口的对象的生命周期,因为TForm类不继承TinterfacedObject而Delphi不支持多重继承,所以我不能将TInterfacedObject混合到继承链中.如果表单被销毁而某些其他代码包含表单传递的一个接口引用,则这种情况可能导致访问冲突.谁能想到这个问题的好方法呢?
这是输出,F~但我期待~F
#include <iostream>
struct Foo {
int _x;
operator const int & () const {return _x;}
~ Foo () {std :: cout << "~";}
};
void foo (const int &)
{
std :: cout << "F";
}
int main ()
{
foo (Foo ());
}
Run Code Online (Sandbox Code Playgroud)
我把它构建为一个反例,表明最重要的const是一个例外而不是规则.它通常写成
当const引用绑定到临时引用时,该临时值的生存期将延长到引用的生命周期
我试图说明,虽然Foo()是临时的,_x转换运算符返回的引用不是,并且上面的代码是不安全的.
但是输出似乎证明了这个例子是安全的,临时的生命周期Foo()是由对其成员之一的const引用的存在而扩展的.
这是正确的吗?标准中的哪个指定了?
可能重复:
我可以在C++中重新开始而不会再次失败吗?
考虑一下T* o = new(T())T,其中定义了一个拷贝构造函数.还假设表达式new使用默认值::operator new()
要重新使用为o分配的内存,而不是删除对象delete o,标准是否允许以下顺序:
o->~T()明确打电话delete o我也问这个,因为我不明白为什么std::map<T, V>(或它operator[]具体),例如,如果上述序列可以在没有这个要求的情况下工作,则需要T定义一个适当的赋值运算符.我怀疑地图是以这种方式设计的,因为operator=()复制构造函数可以有不同的语义,因为大多数时候它们只是以相同的方式实现.
我正在考虑创建一个代表同步原语所有权的类,如下所示:
class CCriticalSectionLock
{
public:
CCriticalSectionLock( CCriticalSection &cs ) : cs( cs )
{ cs.Enter(); }
~CCriticalSectionLock()
{ cs.Leave(); }
private:
CCriticalSection &cs;
};
Run Code Online (Sandbox Code Playgroud)
这似乎是一种在函数期间获取所有权并确保即使存在多个退出点或例外也可以释放所有权的好方法.但是,它确实引发了一些关于编译器何时会对各种事物进行评估的细微问题.考虑以下用途:
int MyMethod( void )
{
not_locked(); // do something not under lock
CCriticalSectionLock myLock( someCriticalSection );
locked(); // do something under lock
return ...; // some expression
}
Run Code Online (Sandbox Code Playgroud)
据我所知,C++一生规则将保证not_locked()会被调用之前采取锁,并locked()同时持有锁会被调用.
但是,我不太清楚的是,何时返回的表达式将根据锁定析构函数的调用点进行计算.是否保证在析构函数之前计算表达式?我会这么认为,但我不是百分百肯定,如果不是,它可能导致非常微妙,间歇性,难以发现的错误!
以下代码是否有效C++,根据标准(折扣... s)?
bool f(T& r)
{
if(...)
{
r = ...;
return true;
}
return false;
}
T x = (f(x) ? x : T());
Run Code Online (Sandbox Code Playgroud)
众所周知,在这个项目使用的GCC版本中编译(4.1.2和3.2.3 ...甚至没有让我开始...),但应该吗?
编辑:我添加了一些细节,例如f()概念在原始代码中的样子.基本上,它意味着在某些条件下初始化x.
假设我有一个可以异步运行某些代码的类,并且该异步代码使用该类实例来执行调用成员函数,读取数据成员等操作.显然,类实例必须比后台线程更长,以便进行这些访问.安全.通过在析构函数中加入后台线程来确保这一点就足够了吗?例如:
#include <iostream>
#include <thread>
class foo final
{
public:
foo() = default;
void bar() {
std::cout << "Hopefully there's nothing wrong with using " << this << "\n";
}
void bar_async() {
if (!m_thread.joinable()) {
m_thread = std::thread{&foo::bar, this};
}
}
~foo() {
if (m_thread.joinable()) {
std::cout << "Waiting for " << m_thread.get_id() << "\n";
m_thread.join();
}
}
private:
std::thread m_thread;
};
int main() {
foo f;
f.bar_async();
}
Run Code Online (Sandbox Code Playgroud)
具体来说,我担心对象生存期规则:
对于析构函数不是微不足道的类类型的任何对象,生命周期在析构函数的执行开始时结束.
...在对象的生命周期结束之后,在重用或释放对象占用的存储之前,以下使用标识该对象的glvalue表达式是未定义的:...
- 访问非静态数据成员或调用非静态成员函数.
但对我来说,严格阅读上述内容也意味着this->bar()从内部~foo() …
我有一个std::packaged_task包含lambda的lambda,它通过复制捕获变量.当这个std::packaged_task被删除,我希望在lambda里面的变量生活是破坏,但我注意到,如果我得到了相关std::future为此std::packaged_task,该future对象扩展拉姆达内部变量的生存期.
例如:
#include <iostream>
#include <future>
class Dummy
{
public:
Dummy() {std::cout << this << ": default constructed;" << std::endl;}
Dummy(const Dummy&) {std::cout << this << ": copy constructed;" << std::endl;}
Dummy(Dummy&&) {std::cout << this << ": move constructed;" << std::endl;}
~Dummy() {std::cout << this << ": destructed;" << std::endl;}
};
int main()
{
std::packaged_task<void()>* p_task;
{
Dummy ScopedDummy;
p_task = new std::packaged_task<void()>([ScopedDummy](){std::cout << "lambda call with: " << &ScopedDummy …Run Code Online (Sandbox Code Playgroud) 在当前版本的C ++标准草案中,[basic.life] / 1 指出:
对象或引用的生存期是对象或引用的运行时属性。如果变量是默认初始化的,则被称为具有空虚的初始化;如果变量是类类型或其(可能是多维的)数组,则该类类型具有琐碎的默认构造函数。类型为T的对象的生存期始于以下情况:
获得具有适合T型的对齐方式和大小的存储,并且
它的初始化(如果有的话)已经完成(包括真空初始化)([dcl.init]),
除了对象是联合成员或其子对象的情况外,其生存期仅在该联合成员是联合中的初始化成员([dcl.init.aggr],[class.base.init])或按照[class.union]。[...]
从该段我知道,工会会员开始其存在的唯一途径是:
mem-initializer),或者然而,唯一的规范在[class.union]段落指定一个联合成员如何开始其生命周期是[class.union] / 5(但它仅适用于特定类型的,即,或者non-class,non-array或class类型与trivial构造是未删除或此类数组)。
下一个段落[class.union] / 6(包含一个注释和一个示例,因此不包含规范性文本)描述了一种通过使用placement new-expression,例如来更改联合的活动成员的方法new (&u.n) N;,其中
struct N { N() { /* non-trivial constructor */ } };
struct M { M() { /* non-trivial constructor */ } };
union
{
N n;
M m;
} u;
Run Code Online (Sandbox Code Playgroud)
我的问题是在标准中指定new (&u.n) N;从哪里开始的生命周期 …
object-lifetime ×10
c++ ×9
c++11 ×2
const ×1
delphi ×1
destructor ×1
interface ×1
lambda ×1
malloc ×1
reference ×1
return ×1
scope ×1
static-cast ×1
std-future ×1
unions ×1