我发现(感谢StackOverflow注释)我的代码中存在安全漏洞:
std::vector<std::unique_ptr<Item>> items;
template<class... TS> Item& create(TS&&... mArgs)
{
auto item(new Item(std::forward<TS>(mArgs)...);
items.emplace_back(item); // Possible exception and memory leak
return *item;
}
Run Code Online (Sandbox Code Playgroud)
基本上,如果抛出Item,使用raw 分配new可能会泄漏内存emplace_back.
解决方案永远不会使用raw new,而是std::unique_ptr在方法体中使用right.
std::vector<std::unique_ptr<Item>> items;
template<class... TS> Item& create(TS&&... mArgs)
{
auto item(std::make_unique<Item>(std::forward<TS>(mArgs)...);
items.emplace_back(std::move(item));
return *item; // `item` was moved, this is invalid!
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,返回item是无效的,因为我不得不item使用std::move它来将它放入items容器中.
我想不出一个需要item在另一个变量中存储地址的解决方案.然而,原始(错误)解决方案非常简洁易读.
是否有更优雅的方式返回std::unique_ptr被移动到容器中的位置?
我正在 GNU/Linux 上学习 x86 汇编,并且正在尝试编写一个程序,从 stdin 读取用户输入并将其打印在 stdout 上。
以下代码确实有效,但如果用户输入的字符串的大小小于 100 个字节,它会打印额外的字符。
section .data
str: db 100 ; Allocate buffer of 100 bytes
section .bss
section .text
global _start
_start:
mov eax, 3 ; Read user input into str
mov ebx, 0 ; |
mov ecx, str ; | <- destination
mov edx, 100 ; | <- length
int 80h ; \
mov eax, 4 ; Print 100 bytes starting from str
mov ebx, 1 ; |
mov ecx, str …Run Code Online (Sandbox Code Playgroud) class Item { };
class Wrapper
{
Item i;
Wrapper(const Item& mI) : i{mI} { }
Wrapper(Item&& mI) : i{std::move(mI)} { }
};
Item createItem()
{
Item result;
// ...
return result; // No `std::move` needed here
}
Wrapper createWrapper()
{
Wrapper result{createItem()}; // `std::move(createItem())` ?
return result;
}
Run Code Online (Sandbox Code Playgroud)
createItem()无需致电即可高效返回std::move.
createWrapper()使用返回值createItem()并希望调用Wrapper::Wrapper(Item&&)构造函数.
是否有必要使用Wrapper result{std::move(createItem())};或Wrapper result{createItem()};足够?
假设我有一个容器对象来存储std::vector多态子.
struct Child
{
Child(Parent& mParent) { /* ... */ }
virtual ~Child() { }
};
class Parent
{
private:
std::vector<std::unique_ptr<Child>> children;
template<typename T, typename... TArgs>
auto& mkChild(TArgs&&... mArgs)
{
// `static_assert` that `T` is derived from `Child`...
children.emplace_back(std::make_unique<T>(std::forward<TArgs>(mArgs)...));
return *children.back();
}
public:
template<typename T, typename... TArgs>
auto& add(TArgs&&... mArgs)
{
mkChild<T>(std::forward<TArgs>(mArgs)...));
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
现在我可以使用这样的Parent类:
int main()
{
Parent p;
p.add<Child1>(some_args1).add<Child2>(some_args2);
}
Run Code Online (Sandbox Code Playgroud)
虽然这种语法实现了我想做的事情(将子项添加到单个父项中),但我觉得很难阅读,特别是在我的实际用例中.
我真的很想用operator<<.但我无法想出一种方法来构建孩子.
// Desired syntax
int main()
{
Parent p; …Run Code Online (Sandbox Code Playgroud) c++ constructor operator-overloading variadic-templates c++14
我正在尝试使用Boost.Sprit x3将两个整数的序列匹配成一个std::pair<int, int>.根据文档判断,以下代码应该编译:
#include <string>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
int main()
{
using namespace boost::spirit::x3;
std::string input("1 2");
std::pair<int, int> result;
parse(input.begin(), input.end(), int_ >> int_, result);
}
Run Code Online (Sandbox Code Playgroud)
但是,它只匹配第一个整数.如果我改变std::pair<int, int> result;对int result;,然后打印result,我得到1我的输出.
为什么会这样?这不是int_ >> int_定义匹配(并设置为属性)两个整数的解析器的正确方法吗?
我的一位同事声称,一旦对象的析构函数调用开始,由线程(该对象本身的成员)完成对对象成员的所有访问都是UB.
这意味着std::thread::join如果线程正在访问任何对象的其他成员,则在对象的析构函数期间调用是UB.
我在"对象生命周期"下简要介绍了最新的标准草案,但找不到能给我一个确定答案的东西.
以下代码(在wandbox上)是否引入了未定义的行为?澄清这种互动的标准部分是什么?
struct A
{
atomic<bool> x{true};
thread t;
// Capturing 'this' is part of the issue.
// The idea is that accessing 'this->x' becomes invalid as soon as '~A()' is entered.
// vvvv
A() : t([this]
{
while(x)
{
this_thread::sleep_for(chrono::milliseconds(100));
}
})
{
}
~A()
{
x = false;
t.join();
}
};
int main()
{
A a;
}
Run Code Online (Sandbox Code Playgroud) 有没有办法检查两个可变参数包的串联是否与第三个可变参数包相同.
template<typename... Args>
struct ClassOne
{
}
template<typename... Args>
struct ClassTwo
{
}
template<typename... Args>
struct ClassThree
{
}
template<typename... PackA, typename... PackB, typename... PackC>
void foo(ClassOne<PackA...>, ClassTwo<PackB...>, ClassThree<PackC...>)
{
}
Run Code Online (Sandbox Code Playgroud)
如果PackA ... = PackB ...,PackC,我想foo才能启用...
templates sfinae template-meta-programming variadic-templates c++14
请考虑以下代码段:
struct foo { };
template <typename F>
struct impl : F
{
impl(F&& f) : F{std::move(f)} { }
auto get() { return (*this)(); }
};
template <typename X>
auto returner(X&& x)
{
return impl{[&x]{ return x; }};
// ^~
}
int main()
{
auto x = returner(foo{}).get();
}
Run Code Online (Sandbox Code Playgroud)
是否保证foo{}在returner(foo{}).get()表达的整个过程中都会存活?
或者只是foo{}为了活着returner(foo{}),因此在调用时会导致未定义的行为impl::get()?
标准在[class.temporary]中说:
临时对象被破坏,作为评估(词法上)包含创建它们的点的完整表达式的最后一步.
一个完整的表达是
一个未评估的操作数,
一个常数表达式,
init-declarator或mem-initializer,包括初始化程序的组成表达式,
调用在临时对象([class.temporary])以外的对象的生命周期结束时生成的析构函数,或者
一个表达式,它不是另一个表达式的子表达式,也不是完整表达式的一部分.
我不知道是否完全表达有关 …
以下代码段:
struct a
{
[[nodiscard]] friend int b();
};
Run Code Online (Sandbox Code Playgroud)
产生在编译时这个错误clang++ (trunk 342102)有-std=c++17:
<source>:3:5: error: an attribute list cannot appear here
[[nodiscard]] friend int b();
^~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
删除friend或添加正文以b防止错误.
g++ (trunk) 编译代码就好了.
关于godbolt的实例:https://gcc.godbolt.org/z/ttTDuZ
这是一个clang++错误吗?或者标准中是否有一些规则使得此代码格式错误?
如果clang++是正确的,将friend成员函数标记为什么的正确方法是[[nodiscard]]什么?
constexpr我想为一个类提供Color如下功能:
// color.hpp
struct Color
{
Color(int r, int g, int b, int a);
static const Color Red;
// ...
};
// color.cpp
Color::Color(int r, int g, int b, int a) { /* ... */ }
const Color Color::Red(255, 0, 0, 255);
// ...
Run Code Online (Sandbox Code Playgroud)
我的愿望是保持此类的 API 不变,因此我想完全删除color.cpp并对头文件进行以下更改:
// color.hpp
struct Color
{
constexpr Color(int r, int g, int b, int a) { /* ... */ }
inline static constexpr Color Red{255, 0, 0, 255};
// …Run Code Online (Sandbox Code Playgroud) c++ ×8
c++11 ×3
c++14 ×3
c++17 ×3
assembly ×1
attributes ×1
boost-fusion ×1
constexpr ×1
constructor ×1
emplace ×1
lifetime ×1
linux ×1
move ×1
nasm ×1
return ×1
return-value ×1
sfinae ×1
static ×1
templates ×1
unique-ptr ×1
x86 ×1